Что делать с очередью SMS при обрыве SMPP-сессии?

Что делать с очередью SMS при обрыве SMPP-сессии?

Статья от 29 сентября 2026 года. При обрыве связи между вашей системой и SMS-шлюзом через SMPP часть сообщений может остаться в неопределённом состоянии: шлюз получил их, а подтверждение доставки ещё не пришло к вам. В статье разберём, как не засорить базу клиентов дублями, корректно продолжить отправку после переподключения и настроить логи для быстрого поиска ошибок.

Почему при обрыве SMPP появляются дубли SMS?

SMPP — это открытый протокол для обмена SMS между равноправными узлами, он используется для высоконагруженных рассылок, когда нужно отправлять тысячи сообщений в минуту, а обычный API не справляется с такой нагрузкой. Для малого и среднего бизнеса Беларуси он становится востребованным, когда объём рассылок превышает несколько тысяч сообщений в месяц: например, для сети точек общепита, которая отправляет напоминания о бронях, или для интернет-магазина с рассылкой статусов заказов и акций.

При обрыве соединения клиент (ваша система) не получает подтверждения от шлюза о том, какие именно сообщения были приняты. Если вы просто повторно отправите всю очередь, которая была в работе на момент обрыва, получатели получат дубли. Это особенно критично для напоминаний о платежах, подтверждений заказов или акционных предложений: два одинаковых сообщения подряд вызывают раздражение, а не лояльность.

Дубли возникают по нескольким причинам. Во-первых, шлюз мог принять PDU (protocol data unit — единицу данных протокола) и поставить сообщение в очередь на отправку оператору, но TCP-соединение оборвалось до того, как ответ submit_sm_resp вернулся вашей системе. Во-вторых, при агрессивной политике повтора некоторые библиотеки автоматически перепосылают весь буфер без проверки состояния предыдущей попытки. В-третьих, если у вас нет локального журнала идентификаторов, вы физически не можете отделить «точно не отправленные» сообщения от «возможно отправленных».

Как проверить, какие сообщения уже дошли до шлюза перед повторной отправкой?

Для решения этой проблемы нужно вести журнал всех идентификаторов отправленных сообщений и их статусов. После переподключения вы сверяете этот журнал с данными от шлюза: только те сообщения, у которых нет подтверждения о доставке (DLR-отчёта), стоит отправлять повторно. DLR-отчёты — это стандартный механизм SMPP, который позволяет отслеживать, дошло ли сообщение до оператора получателя. Если вы используете SMPP-протокол версии 3.4, поддержка таких отчётов встроена в спецификацию, для версии 1.0 (только отправка) придётся дополнительно согласовывать этот функционал с провайдером шлюза.

На smpp.by SMPP-шлюз поставляется с предустановленным журналом идентификаторов сообщений и автоматической сверкой DLR-отчётов, так что вам не нужно разрабатывать этот функционал с нуля. Вы получаете готовое решение с поддержкой версии SMPP 3.4 и полной прозрачностью доставки каждой SMS.

Для удобства проверки можно настроить автоматическую сверку по трём полям: уникальный идентификатор сообщения в вашей системе, идентификатор message_id, который вернул шлюз в submit_sm_resp, и статус из DLR-отчёта. Пока все три поля не заполнены — сообщение считается незавершённым. Именно такие записи подлежат повторной обработке после восстановления сессии, но не автоматической отправке: сначала нужно убедиться, что message_id от шлюза отсутствует, то есть PDU точно не был принят.

Практические шаги при обрыве и восстановлении SMPP-сессии

Ниже приведён порядок действий, который позволяет минимизировать риск дублей и потерь при любом типе обрыва — как со стороны вашей сети, так и со стороны шлюза.

  1. Зафиксируйте момент обрыва. Как только TCP-соединение разрывается, запишите в лог временну́ю метку, последний отправленный sequence_number и последний полученный submit_sm_resp. Это базовая точка восстановления.
  2. Заморозьте очередь на отправку. Не отправляйте новые сообщения до переподключения. Продолжение отправки в разорванное соединение только увеличивает неопределённость.
  3. Пересмотрите буфер в полёте (in-flight). Выделите все сообщения, которым был присвоен sequence_number, но для которых не получен submit_sm_resp. Это и есть зона риска для дублей.
  4. Переподключитесь и дождитесь входящих DLR. После восстановления сессии дайте шлюзу несколько секунд, чтобы он мог прислать отложенные отчёты о доставке. Многие шлюзы буферизуют DLR на своей стороне и отдают их сразу после reconnect.
  5. Сверьте буфер в полёте с поступившими DLR. Те сообщения из зоны риска, для которых пришёл DLR, уже обработаны шлюзом — не отправляйте их повторно. Остальные можно ставить в очередь для повтора.
  6. Используйте поле registered_delivery. Убедитесь, что в каждом submit_sm PDU выставлен флаг registered_delivery = 0x01 — это обязательное условие для получения DLR-отчётов.
  7. Настройте интервал переподключения с нарастающей задержкой. Первая попытка — через 5 секунд, вторая — через 15, третья — через 30 и так далее. Это снижает нагрузку на шлюз в момент массового восстановления соединений.

Как малому бизнесу Беларуси проверить качество маршрута SMS до подключения SMPP-шлюза

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

Проверку можно провести самостоятельно ещё на этапе переговоров с провайдером. Для этого:

  • Попросите у провайдера тестовый доступ на 50–100 сообщений. Порядочный шлюз предоставляет тестовый период без предоплаты или с минимальным депозитом.
  • Отправьте тестовые SMS на номера всех основных операторов вашего региона в разное время суток — в рабочие часы и ночью. Время доставки не должно превышать 10–15 секунд для транзакционных сообщений.
  • Проверьте корректность отображения имени отправителя (sender ID). Если вместо вашего бренда абонент видит случайный номер — маршрут не поддерживает буквенные отправители для данного оператора.
  • Запросите у провайдера статистику доставки (delivery rate) по операторам за последние 30 дней. Это не обязательно публичные данные, но добросовестный провайдер готов их показать потенциальному клиенту под NDA.
  • Уточните, прямой ли маршрут используется к белорусским операторам или транзитный через других агрегаторов. Каждое дополнительное звено увеличивает задержку и снижает предсказуемость доставки.

На smpp.by можно запросить тестовый период и получить детальный отчёт по результатам тестовой рассылки в разрезе операторов. Это позволяет принять взвешенное решение до заключения договора, не полагаясь только на слова менеджера.

Типичные ошибки при управлении SMPP-сессией

Даже разработчики с опытом работы с SMPP допускают одни и те же ошибки при первой реализации или при переходе на новый шлюз. Зная их заранее, вы сэкономите время на отладку.

  • Повтор всей очереди без проверки in-flight буфера. Самая распространённая причина дублей. Решение — всегда вести список sequence_number, для которых не получен submit_sm_resp.
  • Отсутствие heartbeat (enquire_link). SMPP предусматривает команду enquire_link для проверки живости соединения. Если не отправлять её регулярно (обычно раз в 30–60 секунд), шлюз может закрыть соединение по таймауту без уведомления, и вы узнаете об обрыве только при следующей попытке отправки.
  • Игнорирование window size. Window size — это максимальное количество PDU, которые можно отправить без ожидания ответа. Если ваш код отправляет сообщения быстрее, чем шлюз успевает отвечать, и не учитывает window size, соединение нестабильно.
  • Хранение логов только в памяти. Если ваш процесс падает вместе с обрывом, вы теряете журнал in-flight сообщений. Логи должны записываться на диск или в базу данных в режиме реального времени.
  • Неправильная кодировка текста. Для кириллических сообщений используется UCS-2 (data_coding = 0x08). Если выставить Latin-1 (0x00), получатель увидит нечитаемые символы. При этом длина сообщения в UCS-2 ограничена 70 символами вместо 160 для GSM7.
  • Отсутствие обработки ошибочных статус-кодов в submit_sm_resp. Если шлюз вернул ненулевой command_status, сообщение не принято. Многие реализации логируют это как успех и никогда не повторяют отправку.

Что писать в логах SMPP-подключения для быстрого разбора инцидентов

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

Минимально необходимый набор полей для каждого события:

  • Временна́я метка с точностью до миллисекунды — для корреляции событий на стороне клиента и шлюза.
  • Тип PDU — submit_sm, submit_sm_resp, deliver_sm, enquire_link и так далее.
  • sequence_number — связывает исходящий PDU с ответом на него.
  • command_status — код результата операции. Ноль означает успех, любое другое значение — ошибку; расшифровку кодов можно найти в спецификации SMPP 3.4.
  • message_id — идентификатор, присвоенный шлюзом; фиксируется из submit_sm_resp. Нужен для сопоставления с DLR-отчётом.
  • Номер получателя — destination_addr в обезличенном или хешированном виде, если того требует политика хранения персональных данных.
  • Статус сессии — CONNECTED, DISCONNECTED, RECONNECTING; помогает быстро найти момент обрыва в логе.

Рекомендуется использовать структурированный формат логов (JSON или key=value), а не вольный текст. Это позволяет фильтровать события по любому полю без написания сложных регулярных выражений. Например, чтобы найти все сообщения, для которых не вернулся DLR в течение 5 минут, достаточно одного запроса к системе агрегации логов.

Разделяйте логи по уровням: DEBUG — для полного трафика PDU (только в тестовой среде), INFO — для смены статуса сессии и итогов отправки каждого сообщения, WARN — для ненулевых command_status и таймаутов, ERROR — для обрывов соединения и исчерпания попыток переподключения. Такая структура позволяет в боевой среде держать уровень INFO и не захламлять диск, а при инциденте переключиться на DEBUG точечно.

FAQ: управление SMPP-сессией при обрыве связи

Что такое in-flight сообщения и почему они опасны при обрыве?

In-flight сообщения — это те PDU, которые ваша система отправила шлюзу, но ещё не получила ответ submit_sm_resp. При обрыве неизвестно, принял ли шлюз эти PDU до разрыва соединения или нет. Если повторить их отправку без проверки, возникнут дубли. Если не повторить — сообщения могут быть потеряны. Поэтому их нужно сверять с DLR-отчётами после переподключения, а не перепосылать автоматически.

Нужно ли мне самому реализовывать логику повтора, или шлюз делает это за меня?

Это зависит от конкретного шлюза. Часть логики повтора может быть на стороне провайдера — например, если шлюз принял PDU, он гарантирует его доставку оператору с несколькими попытками. Но логику переподключения и работы с in-flight буфером всегда реализует клиентская сторона, то есть ваша система. Уточните у провайдера, какие гарантии он даёт по доставке принятых PDU, и зафиксируйте это в договоре или техническом соглашении.

Как часто нужно отправлять enquire_link?

Стандартная рекомендация — раз в 30–60 секунд. Конкретный интервал зависит от настроек таймаута на стороне шлюза. Уточните у провайдера значение session timeout — это максимальное время неактивности, после которого шлюз закрывает соединение. Отправляйте enquire_link примерно в два раза чаще этого значения.

Можно ли использовать несколько одновременных SMPP-сессий для одного аккаунта?

Большинство шлюзов поддерживают несколько одновременных сессий (multi-binding), что позволяет повысить пропускную способность и обеспечить резервирование: при обрыве одной сессии другие продолжают работу. Количество одновременных сессий обычно ограничено тарифным планом. На smpp.by этот параметр согласовывается отдельно в зависимости от ваших потребностей.

Как быстро проверить, работает ли маршрут к нужному оператору прямо сейчас?

Отправьте тестовое сообщение на собственный номер нужного оператора и замерьте время от отправки до получения. Если DLR-отчёт не приходит в течение 30 секунд для транзакционного маршрута — это повод обратиться в поддержку шлюза. Также можно запросить у провайдера актуальный статус маршрута через его панель мониторинга или API проверки доставки, если такой функционал предусмотрен.

Где найти полную спецификацию SMPP 3.4?

Официальная спецификация SMPP 3.4 опубликована организацией SMS Forum и свободно доступна в интернете в формате PDF. Поиск по запросу «SMPP 3.4 specification PDF» выдаёт оригинальный документ. Там описаны все типы PDU, коды ошибок command_status и правила управления сессией, включая порядок переподключения и работу с window size.