Как настроить rate limit для SMS API, чтобы оператор не заблокировал канал

Как настроить rate limit для SMS API, чтобы оператор не заблокировал канал

Rate limit — это ограничение на количество сообщений, которые вы отправляете за единицу времени. Если превысить порог оператора, канал заблокируют: сначала временно, потом — надолго. Статья покажет, как рассчитать безопасную частоту отправки, настроить очередь на стороне приложения и вовремя заметить, что вы приближаетесь к лимиту. Всё применимо и к HTTP API, и к SMPP-подключению.

Почему оператор блокирует SMS-канал?

Оператор следит за трафиком в реальном времени. Когда с одного отправителя приходит поток сообщений выше допустимого, система расценивает это как спам или техническую ошибку. Триггеры блокировки: превышение лимитов частоты, спам-жалобы от абонентов, несоответствие зарегистрированного альфа-имени и запрещённый контент (по данным smsblog.ru). Блокировка бывает мягкой — оператор начинает дропать часть сообщений без уведомления — и жёсткой, когда канал отключают полностью.

Мягкая блокировка коварнее. Вы продолжаете отправлять, платите за каждое сообщение, а до абонентов доходит 40–60 % трафика. Без мониторинга delivery rate такую ситуацию можно не заметить неделями.

Как рассчитать безопасный rate limit?

Точные лимиты зависят от оператора и типа подключения. Транзакционные SMS (коды подтверждения, статусы заказов) обычно допускают более высокую частоту, чем рекламные рассылки. Вот ориентиры для расчёта:

ПараметрHTTP APISMPP
Типичный старт5–10 сообщений/сек10–30 сообщений/сек
Контроль на стороне оператораПо IP и учётной записиПо bind-сессии и альфа-имени
Сигнал превышенияHTTP 429 (Too Many Requests)ESME_RTHROTTLED (0x00000058)
Что делать при сигналеПауза + экспоненциальный back-offУменьшить окно неподтверждённых PDU

Перед запуском рассылки запросите у агрегатора или оператора конкретное значение TPS (transactions per second). Не полагайтесь на «примерно так же, как у всех». Один агрегатор даёт 20 TPS на старте, другой — 5. Разница в четыре раза, и с первым же промо-рассылочным пиком вы эту разницу почувствуете.

Как реализовать очередь и throttling в приложении?

Ограничивать скорость нужно на вашей стороне, до отправки в шлюз. Три рабочих подхода:

  1. Token bucket. Вы «выдаёте» себе фиксированное число токенов в секунду. Каждое сообщение забирает один токен. Токены кончились — сообщение ждёт в очереди. Реализация есть в стандартных библиотеках большинства языков.
  2. Sliding window. Считаете количество отправленных сообщений за последние N секунд. Если счётчик достиг лимита, новые сообщения встают в очередь. Подход хорош для SMPP, где вы и так контролируете окно неподтверждённых операций.
  3. Очередь с приоритетами. Транзакционные SMS (OTP, подтверждения) получают высокий приоритет и отправляются первыми. Рекламные — ждут, если канал загружен. Подробнее о приоритизации трафика написано в статье про настройку очереди SMS с rate limit и приоритетами.

В SMPP-протоколе скорость регулируется ещё и размером окна (window size) — количеством PDU, отправленных без подтверждения. Если выставите окно 50, а оператор ожидает не больше 10, часть сообщений вернётся с ошибкой throttling. Перед запуском под реальной нагрузкой протестируйте поведение при пиковом потоке, обрыве и повторном подключении (по рекомендациям quicktel.ru).

Что делать, когда лимит всё-таки превышен?

Получили HTTP 429 или ESME_RTHROTTLED — не повторяйте запрос мгновенно. Каждый повторный запрос в момент throttling ухудшает репутацию отправителя. Алгоритм:

  1. Зафиксируйте событие в логе с меткой времени и correlation ID.
  2. Выдержите паузу: 1 секунда → 2 → 4 → 8 (экспоненциальный back-off с потолком 30–60 секунд).
  3. Если за пять попыток канал не разблокирован, переключитесь на резервный маршрут или уведомите дежурного.

Для HTTP API отслеживайте код ответа, время выполнения, таймауты и долю неуспешных запросов. На уровне приложения correlation ID должен проходить через CRM, очередь и шлюз, чтобы вы могли восстановить путь конкретного сообщения (по данным smpp.by). Подробнее о том, как вести себя при устойчивом превышении лимитов, — в материале про graceful degradation SMS-рассылки.

Типичные ошибки при настройке rate limit

  • Нет очереди вообще. Приложение шлёт сообщения с той скоростью, с которой их генерирует. При акции или массовой промо-рассылке канал «ложится» за минуты.
  • Одинаковый приоритет для всех SMS. OTP-код для входа в личный кабинет стоит в одной очереди с уведомлением об акции. Клиент ждёт код 40 секунд, уходит и не возвращается.
  • Retry без back-off. Сообщение не ушло — система повторяет его 10 раз за секунду. Оператор видит всплеск и ужесточает ограничения.
  • Игнорирование delivery receipt. Вы не запрашиваете DLR и не знаете, сколько сообщений реально дошло. Проблема с лимитом становится видна, только когда клиенты звонят в поддержку.
  • Жёстко зашитый лимит. Оператор изменил TPS, а ваш код по-прежнему шлёт с прежней скоростью. Лимиты стоит вынести в конфиг или переменные окружения.

Как мониторить, что всё работает?

Минимальный набор метрик для дашборда:

  • Текущий TPS (факт vs. установленный лимит).
  • Доля ответов с throttling-ошибками за последние 5 минут.
  • Delivery rate за час и за сутки.
  • Средняя длина очереди и время ожидания сообщения.

Для SMPP-сессии добавьте контроль enquire_link: клиент регулярно отправляет heartbeat, контролирует ответ enquire_link_resp и переподключается после таймаута (по данным smpp.by). Если heartbeat не вернулся за 30–60 секунд, сессия, скорее всего, потеряна, и дальнейшие submit_sm уйдут в пустоту. Чтобы дубли не уходили при переподключении, проверьте, как у вас устроена идемпотентность SMS API.

Три шага, которые стоит сделать на этой неделе:

  1. Запросите у агрегатора точное значение TPS для вашего альфа-имени и типа трафика — 10 минут на письмо или звонок.
  2. Добавьте в код token bucket или sliding window с лимитом на 80 % от разрешённого TPS (запас на всплески) — 2–4 часа работы разработчика.
  3. Настройте алерт на долю throttling-ошибок выше 1 % за 5 минут — полчаса на подключение к любой системе мониторинга.