Про DPI выше всё верно, добавлю то, что помогает выбрать лечение,
а не только поставить диагноз.
Смена ДЦ помогает не всегда, и это можно проверить заранее. Если режут
по IP-подсетям Telegram — да, другой аплинк спасёт. Если режут по SNI
на этапе TLS-хендшейка, переезд в другой ДЦ той же страны не даст
ничего: имя домена уходит в открытом виде и его видно везде одинаково.
Различить за минуту. Сначала адрес:
dig +short api.telegram.org
Потом два запроса — по домену и по IP с подменой Host, во втором имя
домена в открытом виде не передаётся:
curl -o /dev/null -s -w "
dns:%{time_namelookup}
conn:%{time_connect}
tls:%{time_appconnect}
total:%{time_total}\n"
https://api.telegram.org/bot/getMe
curl -k -o /dev/null -s -w "%{http_code} %{time_total}\n" -H "Host: api.telegram.org"
https:///bot/getMe
По IP летает, по домену висит — режут по имени, маршрут ни при чём
и менять ДЦ бесполезно. Висят оба — тогда да, IP и маршрут, версия
выше подтверждается.
Заодно смотрите, какая фаза растёт:
— большой time_connect — рвут на TCP
— нормальный time_connect при большом time_appconnect — убивают
TLS-хендшейк, это как раз про SNI
— первые две в норме, растёт только total — это уже обычная
перегрузка канала, и лечится совсем иначе
Теперь про клиент, раз вы про него спрашивали. Причина не в нём, но
именно его настройки решают, будет у вас «иногда подтормаживает» или
«бот встал».
Таймауты. В aiogram по умолчанию 60 секунд, и это очень много. Один
повисший запрос держит очередь, а когда соединение наконец отваливается,
всё накопленное вылетает разом. Симптом «бот молчал, потом ответил всем
сразу» — это почти всегда таймауты, а не сеть.
from aiogram import Bot
from aiogram.client.session.aiohttp import AiohttpSession
bot = Bot(token=TOKEN, session=AiohttpSession(timeout=20))
# у long polling таймаут задаётся отдельно:
# dp.start_polling(bot, polling_timeout=20)
Вебхук вместо long polling. Long polling держит одно долгое соединение,
а такие DPI рвёт охотнее всего. Вебхук — это короткие запросы, плюс при
неудаче Telegram повторяет доставку сам.
Ретраи с экспоненциальной паузой и случайным разбросом. Без разброса все
повторы придут одновременно и добьют то, что и так шатается.
Очередь исходящих в базе вместо «отправить и надеяться»: бот кладёт
сообщение со статусом, отдельный воркер разгребает. При обрыве сообщения
уходят позже, а не теряются. И свой ключ идемпотентности, иначе после
восстановления связи люди получат по три копии.
И залогируйте время каждого запроса с разбивкой по фазам. Ровная
задержка и рваная на глаз одинаковые, а чинятся по-разному.