- Подробное описание работы планировщика с пакетной отправкой - Математика расчета скорости отправки (10-13 сообщений/сек) - Рекомендации по настройке параметров BATCH_SIZE и BATCH_DELAY - Примеры для разных размеров групп пользователей - Troubleshooting распространенных проблем - Объяснение защиты от блокировки Telegram (лимит 30 сообщений/сек)
10 KiB
Настройка планировщика рассылки
Проблема
Telegram имеет лимиты на количество отправляемых сообщений:
- 30 сообщений в секунду для ботов
- При превышении возникает ошибка
Too Many Requests(код 429) - Бот может быть временно заблокирован
Решение
Реализован планировщик пакетной рассылки с контролируемой задержкой между пакетами.
Параметры планировщика
# В файле src/handlers/chat_handlers.py
BATCH_SIZE = 20 # Количество сообщений в одном пакете
BATCH_DELAY = 1.0 # Задержка между пакетами в секундах
Как это работает
-
Получение списка пользователей:
- Загружаются все зарегистрированные пользователи (
is_registered=True) - Исключается отправитель сообщения
- Загружаются все зарегистрированные пользователи (
-
Разбиение на пакеты:
- Пользователи разбиваются на группы по
BATCH_SIZE(по умолчанию 20) - Например, 100 пользователей = 5 пакетов по 20
- Пользователи разбиваются на группы по
-
Параллельная отправка внутри пакета:
- В каждом пакете сообщения отправляются параллельно через
asyncio.gather() - Это ускоряет доставку без превышения лимитов
- В каждом пакете сообщения отправляются параллельно через
-
Задержка между пакетами:
- После отправки пакета выжидается
BATCH_DELAYсекунд - Это предотвращает превышение лимита 30 сообщений/сек
- После отправки пакета выжидается
-
Обработка ошибок:
- Ошибки отправки отлавливаются для каждого пользователя
- Статистика успешных/неуспешных доставок ведется отдельно
Математика
Скорость отправки:
- Пакет из 20 сообщений отправляется параллельно ≈ за 0.5-1 секунду
- Задержка между пакетами: 1 секунда
- Итого: ~20 сообщений за 1.5-2 секунды = 10-13 сообщений/сек
- Это в 2-3 раза меньше лимита Telegram (30/сек)
Пример для 100 пользователей:
- 5 пакетов по 20 сообщений
- Время отправки: 5 × (1 сек отправка + 1 сек задержка) = 10 секунд
- Средняя скорость: 10 сообщений/сек
Пример для 1000 пользователей:
- 50 пакетов по 20 сообщений
- Время отправки: 50 × 2 сек = 100 секунд (1.5 минуты)
- Средняя скорость: 10 сообщений/сек
Настройка параметров
Увеличение скорости
Если нужно быстрее рассылать и у вас стабильное соединение:
BATCH_SIZE = 25 # Больше сообщений в пакете
BATCH_DELAY = 0.8 # Меньше задержка
⚠️ Риск: При > 30 сообщений/сек может быть блокировка
Уменьшение нагрузки
Если возникают ошибки 429 или нестабильное соединение:
BATCH_SIZE = 15 # Меньше сообщений в пакете
BATCH_DELAY = 1.5 # Больше задержка
✅ Безопаснее: Меньше шанс блокировки
Для VIP ботов (верифицированных)
Telegram может повысить лимиты для верифицированных ботов:
BATCH_SIZE = 30 # Можно больше
BATCH_DELAY = 0.5 # Можно быстрее
Пример работы
Код функции
async def broadcast_message_with_scheduler(message: Message, exclude_user_id: Optional[int] = None):
"""Разослать сообщение всем пользователям с планировщиком"""
async with async_session_maker() as session:
users = await get_all_active_users(session)
if exclude_user_id:
users = [u for u in users if u.telegram_id != exclude_user_id]
forwarded_ids = {}
success_count = 0
fail_count = 0
# Разбиваем на пакеты
for i in range(0, len(users), BATCH_SIZE):
batch = users[i:i + BATCH_SIZE]
# Отправляем пакет параллельно
tasks = [_send_message_to_user(message, u.telegram_id) for u in batch]
results = await asyncio.gather(*tasks, return_exceptions=True)
# Подсчитываем статистику
for user, result in zip(batch, results):
if isinstance(result, Exception):
fail_count += 1
elif result is not None:
forwarded_ids[str(user.telegram_id)] = result
success_count += 1
else:
fail_count += 1
# Задержка между пакетами
if i + BATCH_SIZE < len(users):
await asyncio.sleep(BATCH_DELAY)
return forwarded_ids, success_count, fail_count
Статистика для пользователя
После рассылки пользователь видит:
✅ Сообщение разослано!
📤 Доставлено: 95
❌ Не доставлено: 5
Причины неуспешной доставки:
- Пользователь заблокировал бота
- Пользователь удалил аккаунт
- Временные сетевые проблемы
- Ограничения Telegram на стороне получателя
История сообщений
Все ID отправленных сообщений сохраняются в БД:
-- Таблица chat_messages
forwarded_message_ids JSONB
-- Пример данных:
{
"123456789": 12345, -- telegram_id: message_id
"987654321": 12346,
"555555555": 12347
}
Это позволяет:
- Удалять сообщения у всех пользователей через
/delete_msg - Отслеживать кому было доставлено сообщение
- Собирать статистику рассылок
Рекомендации
Для маленьких групп (< 50 пользователей)
Можно использовать параметры по умолчанию:
BATCH_SIZE = 20
BATCH_DELAY = 1.0
Для средних групп (50-200 пользователей)
Рекомендуется:
BATCH_SIZE = 20
BATCH_DELAY = 1.0
Время рассылки: ~20-40 секунд
Для больших групп (200-1000 пользователей)
Рекомендуется:
BATCH_SIZE = 25
BATCH_DELAY = 1.0
Время рассылки: ~1.5-3 минуты
Для очень больших групп (> 1000 пользователей)
Рассмотрите:
- Увеличение
BATCH_SIZEдо 30 - Использование очередей (RabbitMQ, Celery)
- Распределение нагрузки на несколько ботов
Мониторинг
Для отслеживания работы планировщика смотрите логи:
tail -f logs/bot.log | grep "Failed to send"
Каждая неуспешная отправка логируется:
Failed to send message to 123456789: Forbidden: bot was blocked by the user
Failed to send message to 987654321: Bad Request: chat not found
Тестирование
Для тестирования планировщика:
- Создайте несколько тестовых аккаунтов
- Отправьте сообщение через бота
- Проверьте время доставки и статистику
- Настройте параметры под свою нагрузку
Troubleshooting
Ошибка "Too Many Requests"
Симптомы: Бот периодически выдает ошибку 429
Решение:
BATCH_SIZE = 15 # Уменьшить размер пакета
BATCH_DELAY = 1.5 # Увеличить задержку
Медленная рассылка
Симптомы: Рассылка занимает слишком много времени
Решение:
BATCH_SIZE = 25 # Увеличить размер пакета
BATCH_DELAY = 0.8 # Уменьшить задержку
⚠️ Следите за ошибками 429!
Большое количество неуспешных доставок
Причины:
- Пользователи массово блокируют бота
- Проблемы с сетью/сервером
- Некорректные telegram_id в базе
Решение:
- Регулярно очищайте неактивных пользователей
- Мониторьте состояние сервера
- Валидируйте данные при регистрации
Итого
✅ Защита от блокировки: Лимит 30 сообщений/сек не превышается
✅ Гибкость: Легко настроить под свою нагрузку
✅ Статистика: Точный подсчет успешных/неуспешных доставок
✅ История: Все ID сохраняются для модерации
✅ Параллелизм: Быстрая отправка внутри пакета
Рекомендуемые параметры:
BATCH_SIZE = 20
BATCH_DELAY = 1.0
Это обеспечивает баланс между скоростью и безопасностью.