Some checks reported errors
continuous-integration/drone/push Build encountered an error
- Подробное описание работы планировщика с пакетной отправкой - Математика расчета скорости отправки (10-13 сообщений/сек) - Рекомендации по настройке параметров BATCH_SIZE и BATCH_DELAY - Примеры для разных размеров групп пользователей - Troubleshooting распространенных проблем - Объяснение защиты от блокировки Telegram (лимит 30 сообщений/сек)
290 lines
10 KiB
Markdown
290 lines
10 KiB
Markdown
# Настройка планировщика рассылки
|
||
|
||
## Проблема
|
||
|
||
Telegram имеет лимиты на количество отправляемых сообщений:
|
||
- **30 сообщений в секунду** для ботов
|
||
- При превышении возникает ошибка `Too Many Requests` (код 429)
|
||
- Бот может быть временно заблокирован
|
||
|
||
## Решение
|
||
|
||
Реализован **планировщик пакетной рассылки** с контролируемой задержкой между пакетами.
|
||
|
||
### Параметры планировщика
|
||
|
||
```python
|
||
# В файле src/handlers/chat_handlers.py
|
||
|
||
BATCH_SIZE = 20 # Количество сообщений в одном пакете
|
||
BATCH_DELAY = 1.0 # Задержка между пакетами в секундах
|
||
```
|
||
|
||
### Как это работает
|
||
|
||
1. **Получение списка пользователей:**
|
||
- Загружаются все зарегистрированные пользователи (`is_registered=True`)
|
||
- Исключается отправитель сообщения
|
||
|
||
2. **Разбиение на пакеты:**
|
||
- Пользователи разбиваются на группы по `BATCH_SIZE` (по умолчанию 20)
|
||
- Например, 100 пользователей = 5 пакетов по 20
|
||
|
||
3. **Параллельная отправка внутри пакета:**
|
||
- В каждом пакете сообщения отправляются параллельно через `asyncio.gather()`
|
||
- Это ускоряет доставку без превышения лимитов
|
||
|
||
4. **Задержка между пакетами:**
|
||
- После отправки пакета выжидается `BATCH_DELAY` секунд
|
||
- Это предотвращает превышение лимита 30 сообщений/сек
|
||
|
||
5. **Обработка ошибок:**
|
||
- Ошибки отправки отлавливаются для каждого пользователя
|
||
- Статистика успешных/неуспешных доставок ведется отдельно
|
||
|
||
### Математика
|
||
|
||
**Скорость отправки:**
|
||
- Пакет из 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 сообщений/сек
|
||
|
||
### Настройка параметров
|
||
|
||
#### Увеличение скорости
|
||
|
||
Если нужно быстрее рассылать и у вас стабильное соединение:
|
||
|
||
```python
|
||
BATCH_SIZE = 25 # Больше сообщений в пакете
|
||
BATCH_DELAY = 0.8 # Меньше задержка
|
||
```
|
||
|
||
⚠️ **Риск:** При > 30 сообщений/сек может быть блокировка
|
||
|
||
#### Уменьшение нагрузки
|
||
|
||
Если возникают ошибки 429 или нестабильное соединение:
|
||
|
||
```python
|
||
BATCH_SIZE = 15 # Меньше сообщений в пакете
|
||
BATCH_DELAY = 1.5 # Больше задержка
|
||
```
|
||
|
||
✅ **Безопаснее:** Меньше шанс блокировки
|
||
|
||
#### Для VIP ботов (верифицированных)
|
||
|
||
Telegram может повысить лимиты для верифицированных ботов:
|
||
|
||
```python
|
||
BATCH_SIZE = 30 # Можно больше
|
||
BATCH_DELAY = 0.5 # Можно быстрее
|
||
```
|
||
|
||
## Пример работы
|
||
|
||
### Код функции
|
||
|
||
```python
|
||
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 отправленных сообщений сохраняются в БД:
|
||
|
||
```sql
|
||
-- Таблица chat_messages
|
||
forwarded_message_ids JSONB
|
||
|
||
-- Пример данных:
|
||
{
|
||
"123456789": 12345, -- telegram_id: message_id
|
||
"987654321": 12346,
|
||
"555555555": 12347
|
||
}
|
||
```
|
||
|
||
Это позволяет:
|
||
- Удалять сообщения у всех пользователей через `/delete_msg`
|
||
- Отслеживать кому было доставлено сообщение
|
||
- Собирать статистику рассылок
|
||
|
||
## Рекомендации
|
||
|
||
### Для маленьких групп (< 50 пользователей)
|
||
|
||
Можно использовать параметры по умолчанию:
|
||
|
||
```python
|
||
BATCH_SIZE = 20
|
||
BATCH_DELAY = 1.0
|
||
```
|
||
|
||
### Для средних групп (50-200 пользователей)
|
||
|
||
Рекомендуется:
|
||
|
||
```python
|
||
BATCH_SIZE = 20
|
||
BATCH_DELAY = 1.0
|
||
```
|
||
|
||
Время рассылки: ~20-40 секунд
|
||
|
||
### Для больших групп (200-1000 пользователей)
|
||
|
||
Рекомендуется:
|
||
|
||
```python
|
||
BATCH_SIZE = 25
|
||
BATCH_DELAY = 1.0
|
||
```
|
||
|
||
Время рассылки: ~1.5-3 минуты
|
||
|
||
### Для очень больших групп (> 1000 пользователей)
|
||
|
||
Рассмотрите:
|
||
- Увеличение `BATCH_SIZE` до 30
|
||
- Использование очередей (RabbitMQ, Celery)
|
||
- Распределение нагрузки на несколько ботов
|
||
|
||
## Мониторинг
|
||
|
||
Для отслеживания работы планировщика смотрите логи:
|
||
|
||
```bash
|
||
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
|
||
```
|
||
|
||
## Тестирование
|
||
|
||
Для тестирования планировщика:
|
||
|
||
1. Создайте несколько тестовых аккаунтов
|
||
2. Отправьте сообщение через бота
|
||
3. Проверьте время доставки и статистику
|
||
4. Настройте параметры под свою нагрузку
|
||
|
||
## Troubleshooting
|
||
|
||
### Ошибка "Too Many Requests"
|
||
|
||
**Симптомы:** Бот периодически выдает ошибку 429
|
||
|
||
**Решение:**
|
||
```python
|
||
BATCH_SIZE = 15 # Уменьшить размер пакета
|
||
BATCH_DELAY = 1.5 # Увеличить задержку
|
||
```
|
||
|
||
### Медленная рассылка
|
||
|
||
**Симптомы:** Рассылка занимает слишком много времени
|
||
|
||
**Решение:**
|
||
```python
|
||
BATCH_SIZE = 25 # Увеличить размер пакета
|
||
BATCH_DELAY = 0.8 # Уменьшить задержку
|
||
```
|
||
|
||
⚠️ Следите за ошибками 429!
|
||
|
||
### Большое количество неуспешных доставок
|
||
|
||
**Причины:**
|
||
- Пользователи массово блокируют бота
|
||
- Проблемы с сетью/сервером
|
||
- Некорректные telegram_id в базе
|
||
|
||
**Решение:**
|
||
- Регулярно очищайте неактивных пользователей
|
||
- Мониторьте состояние сервера
|
||
- Валидируйте данные при регистрации
|
||
|
||
## Итого
|
||
|
||
✅ **Защита от блокировки**: Лимит 30 сообщений/сек не превышается
|
||
✅ **Гибкость**: Легко настроить под свою нагрузку
|
||
✅ **Статистика**: Точный подсчет успешных/неуспешных доставок
|
||
✅ **История**: Все ID сохраняются для модерации
|
||
✅ **Параллелизм**: Быстрая отправка внутри пакета
|
||
|
||
**Рекомендуемые параметры:**
|
||
```python
|
||
BATCH_SIZE = 20
|
||
BATCH_DELAY = 1.0
|
||
```
|
||
|
||
Это обеспечивает баланс между скоростью и безопасностью.
|