Проблема массовой рассылки в Телеграме

98
24 февраля 2022, 17:40

Реализовал бота, который каждые 5 минут парсит один сайт с объявлениями и оповещает пользователей по категориям (0-5 оповещений за один раз).

Все работает хорошо, но вот лимит телеграма в 30 сообщений/секунду всему мешает. Пользователей может быть очень много, а при идеальных обстоятельствах получится отправить только 9000 сообщений за 5 минут. Этого в будущем будет недостаточно. И это еще не учитывая, что пользователи будут вести чат с ботом (настраивать его)

Перебирал разные варианты, вплоть до создания нескольких одинаковых ботов и разделения пользователей по ним. Но это не удобно, поэтому пишу сюда. Какие у вас есть идеи? Спасибо.

Answer 1

Насколько я вижу вам нужно оптимизировать логику работы скрипта. Лимит в 30 сообщений/секунда вы никак не обойдете.

Краткая выжимка из дальнейшего текста

  • Объединяйте несколько уведомлений в одно сообщение, это сократит нагрузку на лимиты в разы.
  • Сегментируйте пользователей и тратьте лимиты на тех, кто в них реально нуждается (таких пользователей всегда будет меньшинство), остальным шлите общие отчеты.
  • Запускайте скрипты условным "потоком", а не интервально раз в 5 минут.
  • Формируйте очереди на отправку и обрабатывайте их в зависимости от важности.
  • Искусственно снижайте нагрузку, вводя плату за "мгновенные" уведомления.
  • Оптимизируйте код для максимальной скорости работы скриптов и минимальных нагрузок

Сегментация пользователей

Для начала я бы рекомендовал вам делить пользователей на активных и пассивных. Положим у вашего бота миллион подписчиков. Их них в лучшем случае 100 000 будут активно проверять объявления в течение дня. Т.е. всех активных пользователей вы сможете перебрать за час (1800 в минуту * 60 = 98 000 пользователей).

Остальным можно отправлять общую сводку раз в сутки в разное время. (900 000 отправок = 10 часов работы, которые будут равномерно распределены в неактивные часы дня).

Запуск скриптов "потоком"

Я бы рекомендовал отойти от идеи парсинга раз в 5 минут и дальнейшего оповещения пользователей к постоянной работе с сайтом. Возможно вам потребуется приобрести proxy для захода на сайт с нескольких IP адресов, дабы не попасть под блокировку со стороны сисадмина сайта объявлений.

Попробуйте сделать массив категорий на сайте объявлений и их парсинг с задержкой в 10-15 секунд (зависит от скорости обработки парсером категории).

После этого сделайте отдельный парсинг категории. Допустим получится 6 категорий. Из этого следует что вам нужно настроить 6 CRON запусков каждую минуту со sleep параметром в n*10 секунд где n - номер скрипта(чтобы скрипты запускались не одновременно, а по очереди). Если категорий 12 - CRON на 2 минуты и т.д.

Точные значения подбирайте сами из нагрузки на ваш сервер.

Очереди на отправку сообщений

Во время парсинга формируйте очередь на отправку уведомлений пользователям. Затем эту очередь обрабатывайте уже непосредственно ботом.

Разделите очередь на новые уведомления и ответы на сообщения пользователей. В первую очередь проверяйте нужно ли кому-то ответить и обрабатывайте в рамках лимита ответы пользователям, потом переходите к отправке новых сообщений.

Помещайте пользователей которым уже отправили сообщение в конец очереди на отправку сообщения.

Объединяйте несколько уведомлений в одно сообщение

Формируйте из нескольких объявлений для пользователя одно сообщение. Тогда не придется отправлять по 0-5 сообщений пользователю раз в 5 минут. Как я уже говорил неактивным пользователям можно отправлять шаблон общей сводки раз в сутки (мол по вашим категориям 10 новых объявлений, смотрите тут).

Для активных пользователей отправляйте сводку за час (при нагрузке в 100 000 активных пользователей, откуда берется эта цифра писал выше).

Искусственно снижайте нагрузку вводя плату

Можете сделать премиум-доступ, условно 5 000 человек, которые заплатили чтобы получать уведомления каждые 5 минут (5 000 / 1800 = 2,7 минуты на отправку всех сообщений).

Доп проверки (на ранних этапах развития), увеличивает нагрузку

Можете дополнительно настроить проверку сколько объектов уже в сообщении. Тогда например как только у пользователя скапливается 5 новых объектов - его сообщение отправляется вне очереди. (не рекомендую, увеличит нагрузку и пожрет лимиты).

Оптимизируйте код

Оптимизируйте код парсера/бота/запросы к БД. Тут сложно давать советы, т.к. не ясно с чем имеем дело, но пару общих принципов могу порекомендовать:

  1. Попробуйте перед запуском парсера проверять изменения на странице через Last-Modified заголовок не загружая саму страницу. Это сократит нагрузку в разы. Подробнее: https://superuser.com/questions/619592/get-modification-time-of-remote-file-over-http-in-bash-script Причина, почему это может не сработать: https://stackoverflow.com/questions/23644436/how-do-i-find-when-a-web-page-was-last-updated
  2. Убивайте скрипт через die как только он перестает быть нужным. Не ждите завершения всего кода.
  3. Один длинный запрос к БД как правило лучше чем несколько коротких.
  4. Последние версии php работают быстрее древних.

Ну и оптимизируйте всю эту схему в зависимости от нагрузок.

Итог

В итоге получится что у вас постоянно формируется очередь отправки сообщений, причем сообщения постоянно дополняются объектами. В итоге к пользователю приходит новое уведомление не с четко заданным интервалом, а по мере работы скрипта.

Это не страшно т.к. пользователи не сидят всё время в телефоне и если уведомление о новом объекте придет на минуту позже - всё в порядке. Другая ситуация с ответами на команды пользователя - тут задержек быть не должно, поэтому очередь ответов должна обрабатываться первой. За лишнюю минуту задержки в отправке уведомления о новых объектах вы сможете обработать 1800 ответов пользователей.

READ ALSO
Как бы вы упростили эту функцию?

Как бы вы упростили эту функцию?

Как бы вы упростили эту функцию? Функции передается массив items, получаемый с сервера (сугубо для вставки текста на кириллице, кириллицу внутри...

90
Как сократить/улучшить js код?

Как сократить/улучшить js код?

Вечер добрый, помогите пожалуйста сократить/улучшить javascript код

170
Prototype, call. Откуда берется второй undefined?

Prototype, call. Откуда берется второй undefined?

Изучаю прототипы и добавляю к ним методы [call, bind, apply] и столкнулся с такой фичейНе понимаю откуда берется undefined

89