ЛОДЖИК ТЕЛЕКОМ
Коммуникации6 августа 2026 г.5 мин

Надёжная SMPP-сессия: bind, enquire_link, reconnect и окно отправки

Как спроектировать устойчивое SMPP-подключение: bind_transceiver, enquire_link, тайм-ауты, reconnect с jitter, окно запросов, sequence_number и защита от дублей.

Два устойчивых канала SMPP передают сообщения через контролируемое окно запросов
Содержание

SMPP-подключение нельзя считать надёжным только потому, что TCP-сокет открыт. Рабочая интеграция должна контролировать состояние bind, обмен enquire_link, время ответа на каждый PDU, размер окна неподтверждённых запросов и восстановление после разрыва. Иначе короткий сетевой сбой превращается в зависшую очередь, повторные SMS или потерю связи между отправкой и DLR.

Из каких состояний состоит соединение

Удобно описать клиент как конечный автомат:

  1. DISCONNECTED — соединения нет, отправка приостановлена;
  2. CONNECTING — устанавливается TCP/TLS-соединение;
  3. BINDING — отправлен bind и ожидается ответ;
  4. BOUND — сессия готова принимать прикладной трафик;
  5. DRAINING — новые сообщения не принимаются, незавершённые запросы закрываются;
  6. UNBINDING — выполняется штатное завершение.

Переход в BOUND разрешается только после успешного bind_resp. Сам факт установления TCP не означает, что учётные данные приняты и SMSC готов обрабатывать submit_sm.

Для двунаправленной работы обычно используют bind_transceiver. Раздельные transmitter/receiver-сессии применяют, если этого требует оператор или архитектура платформы. Конкретное число соединений, режим bind и лимиты необходимо согласовать с провайдером: самовольное открытие дополнительных сессий может привести к throttling или блокировке.

Heartbeat проверяет не только сеть

enquire_link помогает обнаружить соединение, которое формально остаётся открытым, но фактически не передаёт PDU. Интервал heartbeat должен быть меньше сетевых idle-timeout на всём пути — балансировщике, NAT, firewall и стороне SMSC. При этом слишком частые проверки создают лишнюю нагрузку.

Практическая схема включает три независимых таймера:

  • интервал простоя до отправки enquire_link;
  • максимальное ожидание enquire_link_resp;
  • предельное время ответа на прикладной запрос, например submit_sm_resp.

Если ответ не пришёл, соединение следует считать неопределённым, закрыть и создать заново. Бесконечно ждать на старом сокете опаснее, чем выполнить контролируемое переподключение.

Reconnect без эффекта толпы

После сбоя десятки экземпляров клиента могут одновременно попытаться восстановить соединение. Чтобы не перегрузить SMSC, применяют экспоненциальную задержку с jitter, например: 1, 2, 4, 8 секунд с ограничением максимального интервала и случайной составляющей.

Нужны отдельные правила для разных причин:

  • сетевой разрыв — повтор после задержки;
  • временная ошибка bind — ограниченное число попыток и сигнал оператору;
  • неверные учётные данные или запрещённый режим — остановка автоматических повторов;
  • административное завершение — штатный drain и unbind.

Счётчик попыток сбрасывают только после периода устойчивой работы, а не сразу после успешного TCP-connect. Иначе соединение, которое постоянно обрывается после bind, будет повторяться без сдерживания.

Окно запросов и sequence_number

SMPP допускает несколько неподтверждённых запросов в одной сессии. Размер окна определяет, сколько submit_sm может находиться в полёте. Окно 1 упрощает логику, но ограничивает пропускную способность временем ответа. Слишком большое окно повышает скорость, однако увеличивает объём неопределённых операций при разрыве.

Для каждого запроса клиент сохраняет:

  • sequence_number;
  • внутренний идентификатор сообщения;
  • время отправки и дедлайн ответа;
  • номер сессии или поколение подключения;
  • результат submit_sm_resp и полученный message_id.

После reconnect старые ответы нельзя связывать с новым поколением сессии только по номеру последовательности. Счётчик имеет ограниченный диапазон и со временем повторяется, поэтому ключ корреляции должен учитывать контекст соединения.

Размер окна подбирают нагрузочным тестом вместе с расчётом TPS и очередей. Цель — не максимальное число PDU, а стабильная задержка без роста тайм-аутов и throttling.

Что делать с неопределённой отправкой

Самый сложный случай: submit_sm ушёл, но submit_sm_resp не получен из-за разрыва. Нельзя достоверно знать, принял ли SMSC сообщение. Безусловный повтор может создать дубль, а отказ от повтора — пропуск уведомления.

Политика зависит от типа сообщения:

  • для OTP безопаснее выпустить новый код и аннулировать старый, чем повторять тот же текст без контроля;
  • для сервисных уведомлений применяют бизнес-ключ события и ограниченное окно дедупликации;
  • для маркетингового трафика повтор после неопределённого результата обычно менее оправдан;
  • для критичных событий статус сверяют через журнал платформы или согласованный API, если такая возможность доступна.

SMPP сам по себе не даёт сквозной exactly-once доставки. Защита от дублей строится в приложении, очереди и интеграционном слое. Паттерн хранения события и задания на отправку в одной транзакции разобран в статье про transactional outbox для SMS.

DLR живёт дольше сессии

Отчёт о доставке может прийти через другую SMPP-сессию и значительно позже submit_sm_resp. Корреляцию нельзя хранить только в оперативной памяти процесса. После успешного ответа нужно долговременно связать идентификатор платформы, message_id, адресата, маршрут и время отправки.

При нормализации DLR учитывайте формат идентификатора и статусную модель конкретного провайдера. submit_sm_resp подтверждает приём запроса платформой, но не доставку на устройство. Подробнее это различие разобрано в материале о метриках SMS и DLR.

Метрики и сигналы эксплуатации

Минимальный набор наблюдаемости:

  • текущее состояние и возраст каждой сессии;
  • число bind/reconnect и причины разрыва;
  • задержка submit_sm_resp по P50/P95/P99;
  • заполнение окна и число запросов с истёкшим тайм-аутом;
  • частота throttling и постоянных ошибок;
  • возраст и объём очереди по классам сообщений;
  • доля неопределённых отправок и повторов;
  • задержка и полнота входящих DLR.

Алерт только на «socket disconnected» недостаточен. Соединение может быть установлено, но окно заполнено зависшими запросами, очередь растёт, а прикладная доставка остановлена.

Чек-лист испытаний

Перед промышленным запуском проверьте:

  1. разрыв соединения до и после отправки submit_sm;
  2. отсутствие submit_sm_resp и enquire_link_resp;
  3. медленные ответы без полного разрыва;
  4. отклонение bind и изменение учётных данных;
  5. throttling при достижении договорного TPS;
  6. переключение активной сессии при нескольких экземплярах клиента;
  7. повтор sequence_number после перезапуска;
  8. приход DLR после reconnect и перезапуска процесса;
  9. корректный drain во время релиза;
  10. восстановление очереди без массовых дублей.

Практический вывод

Надёжная SMPP-интеграция — это конечный автомат, ограниченное окно запросов, независимые тайм-ауты, backoff с jitter и долговременная корреляция сообщений. Конкретные интервалы и лимиты нельзя копировать из универсального шаблона: их сверяют с параметрами маршрута и проверяют под реалистичной нагрузкой.

Перед подключением к QuickTel зафиксируйте режим bind, число сессий, TPS, окно, heartbeat, правила повторов и формат DLR. Такой контракт позволяет одинаково трактовать сбои приложению, платформе и эксплуатационной команде.

SMSSMPPИнтеграцииОтказоустойчивость

Читайте также