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

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

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

Зачем нужна очередь перед SMPP-шлюзом?

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

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

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

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

Как разделить очередь на компоненты?

Для начала достаточно четырёх частей: источника сообщений, локального хранилища, отправителя и обработчика статусов. Источником выступает сайт или внутренняя программа. Хранилище держит задания до отправки. Отправитель управляет SMPP-сессией. Обработчик обновляет состояние после ответа шлюза и получения DLR.

КомпонентЧто он делаетЧто сохранить
ИсточникСоздаёт задание на SMSНомер, текст, тип сообщения, внешний идентификатор
Локальная очередьХранит задания до результатаСтатус, время создания, число попыток, время следующей попытки
SMPP-отправительОткрывает сессию и передаёт сообщенияИдентификатор сообщения у шлюза, код ответа
Обработчик DLRПолучает сведения о доставкеФинальный статус, текст отчёта, время получения

В простом варианте очередь можно хранить в базе данных приложения. Для каждого задания создайте поля: уникальный ключ, номер получателя, текст, приоритет, статус, число попыток и дату следующей обработки. Сообщение со статусом pending ждёт отправки, processing временно занято отправителем, submitted принято шлюзом, а delivered подтверждено отчётом.

Статус submitted не стоит считать доставкой. Он показывает, что шлюз принял операцию или вернул идентификатор для дальнейшего отслеживания. Если бизнесу нужно видеть реальный результат, приложение должно сопоставить этот идентификатор с DLR и обновить карточку сообщения.

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

Как обработать обрыв соединения и повторную отправку?

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

Повторную попытку запускайте с увеличивающимся интервалом. Например, после первого сбоя приложение ждёт короткий период, после следующего увеличивает паузу, а затем ограничивает частоту повторов. Такой подход не создаёт постоянный поток запросов в момент, когда канал ещё недоступен.

У каждого сообщения должен быть предел технических попыток или срок хранения. После его достижения запись переводится в состояние failed и попадает в список для проверки. Бесконечный повтор опасен: одна неисправная запись способна занимать очередь и мешать новым сообщениям.

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

Заранее определите, какие ошибки повторяются, а какие требуют ручной проверки. Обрыв TCP-соединения, тайм-аут и временная недоступность шлюза обычно возвращают запись в очередь. Ошибка формата номера, пустой текст или недопустимый параметр сообщения требуют исправления данных. Повторять такую операцию без изменения записи бессмысленно.

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

Как не допустить дубли при восстановлении связи?

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

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

Разделяйте состояние попытки и состояние сообщения. Попытка фиксирует время передачи, ответ SMPP и ошибку соединения. Сообщение хранит общий результат: ждёт отправки, принято шлюзом, доставлено, временно отложено или окончательно завершено. Благодаря этому администратор видит историю и понимает, что произошло после сбоя.

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

Как проверить очередь до запуска в рабочем режиме?

Тестируйте архитектуру на сценариях, которые приводят к потере сообщений. Остановите интернет-канал, отключите SMPP-сессию, перезапустите отправитель и проверьте состояние базы. После восстановления связи убедитесь, что записи вернулись в обработку и не появились дважды.

Проверьте отдельно маленький поток и пиковую загрузку. Для SMPP имеют значение скорость установления сессии, число неподтверждённых операций в окне, поведение при обрыве и повторном подключении. Эти параметры рекомендуют проверять под реальной нагрузкой до перехода в рабочий режим (QUICKTEL).

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

Для контроля DLR задайте отдельный период ожидания. Если отчёт не пришёл, сообщение не следует автоматически объявлять доставленным. Варианты действий зависят от сценария: поставить запись на дополнительную проверку, показать оператору неопределённый статус или запустить ограниченную переотправку. Логику автоматической проверки DLR и повторной отправки можно вынести в отдельный процесс, описанный в материале о проверке DLR-статусов через SMPP.

Перед запуском согласуйте с провайдером SMPP размер окна, ограничения на скорость, формат номера и правила получения DLR. В тесте используйте реальные сетевые условия, а не только успешный запуск одного сообщения. Очередь готова к работе, когда после каждого сбоя понятно, где находится запись и какое действие выполнит система.

Типичные ошибки при настройке локальной очереди

  • Хранить задания только в оперативной памяти процесса. После перезапуска они исчезают вместе с очередью.
  • Удалять запись сразу после отправки в SMPP. В этом случае нельзя проверить DLR и разобрать спорный тайм-аут.
  • Считать ответ шлюза подтверждением доставки. Принятие операции и доставка на телефон имеют разные статусы.
  • Запускать бесконечные повторы без паузы и ограничения. Одна неисправная запись забивает очередь.
  • Не блокировать запись на время обработки. Два экземпляра отправителя могут передать одно сообщение одновременно.
  • Проверять только успешное соединение и не тестировать обрыв во время передачи.

3 шага, которые можно сделать на этой неделе:

  1. Описать состояния сообщения и добавить в хранилище поля для попыток, времени следующей обработки и идентификатора шлюза.
  2. Вынести отправку в отдельный процесс с повторным подключением, паузой после ошибки и защитой от параллельной обработки одной записи.
  3. Провести тест с отключением связи, затем проверить журнал, повторную отправку и сопоставление результата с DLR.

Для бизнеса с небольшим потоком достаточно начать с очереди в существующей базе и одного отправителя. При росте трафика архитектуру расширяют отдельными воркерами, приоритетами и несколькими SMPP-каналами. На площадке smpp.by такую схему можно связать с SMPP-шлюзом, API-интеграцией и аналитикой трафика, сохранив в центре системы понятное состояние каждого сообщения.