Масштабирование IV: Ограничения на флуд
Telegram ограничивает количество сообщений, которые ваш бот может отправлять каждую секунду. Это означает, что любой ваш API-запрос может завершиться ошибкой с кодом 429 (Too Many Requests) и заголовком retry
, как указано здесь. Это может произойти в любой момент.
Существует только один правильный способ разрешения таких ситуаций:
- Подождать указанное количество секунд.
- Повторить запрос.
К счастью, для этого существует плагин auto
Этот плагин очень простой. Он буквально просто ждёт и повторяет запрос. Однако его использование имеет серьезные последствия: любой запрос может быть медленным. Это означает, что когда вы запускаете бота на вебхуках, вам технически придется использовать очередь, что бы вы ни делали, или же вам нужно настроить плагин auto-retry таким образом, чтобы он никогда не занимал много времени - но тогда ваш бот может пропустить некоторые запросы.
Что такое точные пределы
Они не определены.
Смиритесь с этим.
У нас есть несколько хороших идей о том, сколько запросов вы можете выполнить, но точные цифры неизвестны. (Если кто-то говорит вам о реальных ограничениях, значит, он плохо информирован). Ограничения — это не просто жесткие пороги, которые вы можете узнать, экспериментируя с Bot API. Скорее, это гибкие ограничения, которые меняются в зависимости от запросов вашего бота, количества пользователей и других факторов, не все из которых известны.
Вот несколько заблуждений и ложных представлений об ограничениях запросов.
- Мой бот слишком новый, чтобы получать ошибки ожидания флуда.
- Мой бот не получает достаточно трафика, чтобы получать ошибки ожидания флуда.
- Эта функция моего бота используется недостаточно, чтобы получать ошибки ожидания флуда.
- Мой бот оставляет достаточно времени между вызовами API, чтобы не получать ошибки ожидания флуда.
- Этот конкретный вызов метода не может получать ошибки ожидания флуда.
get
не может получать ошибки ожидания флуда.Me get
не может получать ошибки ожидания флуда.Updates
Все это неверно.
Давайте перейдем к тому, что мы знаем.
Безопасные предположения о лимитах запросов
Из Bot FAQ мы знаем несколько пределов, которые нельзя превышать никогда.
“При отправке сообщений в конкретном чате не отправляйте более одного сообщения в секунду. Мы можем разрешить короткие всплески, превышающие этот лимит, но в конечном итоге вы начнете получать 429 ошибку.”
Здесь все должно быть предельно ясно. Плагин auto-retry делает это за вас.
“Если вы отправляете массовые уведомления нескольким пользователям, API не позволит отправлять более 30 сообщений в секунду или около того. Для достижения наилучших результатов следует распределять уведомления на большие интервалы по времени (8-12 часов).”
Это относится только к массовым уведомлениям, т.е. если вы активно рассылаете сообщения многим пользователям. Если вы просто отвечаете на сообщения пользователей, то не проблема отправить 1,000 или более сообщений в секунду.
Когда в Bot FAQ говорится, что вам следует “рассмотреть возможность распределения уведомлений по большим интервалам”, это не означает, что вы должны добавлять какие-либо искусственные задержки. Напротив, главный вывод заключается в том, что массовая рассылка уведомлений — это процесс, который займет много часов. Вы не можете рассчитывать на то, что все пользователи получат сообщения мгновенно и в одно и то же время.
“Также обратите внимание, что ваш бот не сможет отправлять более 20 сообщений в минуту одной и той же группе.”
Опять же, довольно ясно. Совершенно не связано с массовыми уведомлениями или количеством сообщений, отправляемых в группе. И опять же, плагин auto-retry позаботится об этом за вас.
Есть еще несколько известных ограничений, о которых стало известно за пределами официальной документации Bot API. Например, известно, что боты могут редактировать не более 20 сообщений в минуту в одном групповом чате. Однако это исключение, и мы также должны предположить, что эти ограничения могут быть изменены в будущем. Таким образом, эта информация не влияет на то, как писать вашего бота.
Например, троттлинг бота на основе этих цифр по-прежнему является плохой идеей:
Троттлинг
Некоторые считают, что превышение лимита запросов — это плохо. Они предпочитают знать точные ограничения, чтобы иметь возможность троттлить своего бота.
Это неверно. Лимиты запросов — это инструмент, полезный для контроля флуда, и если вы будете действовать соответствующим образом, они не окажут никакого негативного влияния на вашего бота. Иными словами, превышение лимитов не приводит к банам. А вот их игнорирование — да.
Более того, согласно Telegram, знать точные лимиты “бесполезно и вредно”.
Это бесполезно, потому что даже если бы вы знали лимиты, вам все равно пришлось бы обрабатывать ошибки ожидания флуда. Например, сервер Bot API возвращает 429, когда он выключается для перезагрузки во время технического обслуживания.
Это вредно, потому что если вы будете искусственно задерживать некоторые запросы, чтобы не попасть в лимиты, производительность вашего бота будет далека от оптимальной. Вот почему вы всегда должны делать свои запросы как можно быстрее, но уважать все ошибки ожидания флуда (используя плагин auto-retry).
Но если троттлить запросы вредно, то как сделать трансляцию?
Как транслировать сообщения
Трансляцию можно осуществлять, следуя очень простому подходу.
- Отправьте сообщение пользователю.
- Если вы получите ответ 429, подождите и повторите попытку.
- Повторите.
Не добавляйте искусственных задержек. (Они делают трансляцию медленнее).
Не игнорируйте ошибки 429. (Это может привести к бану).
Не отправляйте много сообщений параллельно. (Вы можете отправлять очень мало сообщений параллельно (может быть, 3 или около того), но это может быть сложным для реализации).
Шаг 2 в приведенном выше списке выполняется автоматически плагином auto-retry, поэтому код будет выглядеть следующим образом:
bot.api.config.use(autoRetry());
for (const [chatId, text] of broadcast) {
await bot.api.sendMessage(chatId, text);
}
2
3
4
5
Самое интересное здесь это то, что будет представлять собой broadcast
. Вам нужно, чтобы все ваши чаты хранились в некоторой базе данных, и вы должны иметь возможность медленно получать их все.
В настоящее время вам придется реализовать эту логику самостоятельно. В будущем мы хотим создать плагин для трансляции. Мы будем рады принять ваш вклад! Присоединяйтесь к нам здесь.