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

Резервирование SMS-маршрутов: каскад без дублей и задержек

Как построить переключение SMS-маршрутов: критерии отказа, TTL, circuit breaker, идемпотентность, защита от дублей, совместимость отправителя и проверка каскада.

Поток SMS автоматически переключается между основным и резервным маршрутами
Содержание

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

Какие отказы должен закрывать каскад

Маршрут может стать непригодным на разных этапах:

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

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

Модель состояния важнее списка поставщиков

Для каждой попытки полезно хранить отдельную запись:

business_event_id
message_id
attempt_id
route_id
submitted_at
deadline_at
provider_message_id
submission_result
final_status

business_event_id связывает все попытки с одним уведомлением. attempt_id различает технические отправки, а provider_message_id используется для запросов статуса и обработки DLR.

Минимальная модель результата отправки:

  • not submitted — соединение не установлено или запрос отклонён до принятия;
  • accepted — поставщик подтвердил приём и вернул идентификатор;
  • unknown — клиент не получил однозначного ответа;
  • terminal failure — пришёл финальный отрицательный статус;
  • delivered — получен финальный положительный DLR.

Состояние unknown нельзя автоматически приравнивать к отказу. Сначала нужна сверка по клиентскому идентификатору, запрос статуса или короткое окно ожидания — в зависимости от возможностей интеграции.

Как описать допустимые маршруты

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

  • страна и мобильная сеть получателя;
  • зарегистрированное имя отправителя;
  • тип трафика: OTP, транзакционный или маркетинговый;
  • поддерживаемая кодировка и длинные сообщения;
  • максимальный TPS и доступная квота;
  • требования к сроку доставки;
  • наличие DLR и запроса статуса;
  • согласованные часы и коммерческие условия.

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

TTL ограничивает бессмысленные повторы

У каждого уведомления должен быть срок полезности. OTP после истечения кода, напоминание после начала события и сообщение о курьере после завершения доставки уже не решают бизнес-задачу.

В очередь стоит записывать:

  • время создания события;
  • крайний срок первой отправки;
  • крайний срок всех повторов;
  • максимальное число маршрутных попыток;
  • допустимость перехода в другой канал.

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

Circuit breaker защищает от лавины

Если маршрут деградировал, продолжать направлять на него каждое новое сообщение дорого и медленно. Circuit breaker временно исключает маршрут после устойчивого сигнала проблемы.

Для решения лучше сочетать несколько показателей:

  • долю сетевых и серверных ошибок;
  • P95 времени ответа;
  • долю отклонённых submit-запросов;
  • P95 времени до финального DLR;
  • долю доставки внутри целевого окна;
  • возраст самого старого сообщения в очереди;
  • состояние SMPP bind и частоту переподключений.

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

Как не отправить одно SMS дважды

Защита от дублей начинается до обращения к поставщику:

  1. Бизнес-сервис создаёт стабильный ключ идемпотентности.
  2. Коммуникационный сервис сохраняет событие и план отправки атомарно.
  3. Каждая попытка получает уникальный технический идентификатор.
  4. Принятый поставщиком запрос не повторяется без проверки его состояния.
  5. Все DLR обрабатываются идемпотентно и связываются с конкретной попыткой.
  6. После первого подтверждённого delivered остальные незапущенные попытки отменяются.

Если поставщик поддерживает клиентский идентификатор и идемпотентность API, используйте их. Но локальная защита всё равно нужна: один и тот же бизнес-запрос может прийти повторно из CRM, очереди или планировщика.

Надёжный webhook DLR дополняет эту схему: повторные и пришедшие не по порядку статусы не должны повторно запускать бизнес-действие.

Разделяйте ретрай и переключение маршрута

Повтор на том же маршруте полезен при короткой сетевой ошибке или ограничении скорости. Переключение требуется, когда проблема относится к самому маршруту или его качеству. Для каждого класса ошибки задайте отдельное действие:

Сигнал Типовая реакция
HTTP 429 или throttling повтор с backoff в пределах TTL
отказ соединения короткий повтор, затем резервный маршрут
явный запрет номера или шаблона завершение без каскада
тайм-аут после submit сверка состояния, не мгновенный дубль
рост задержки DLR снижение веса или временное исключение маршрута
истёкший TTL завершение без новой попытки

Коды ошибок поставщиков нужно нормализовать в собственную модель. Иначе одинаковые причины будут запускать разные действия только из-за формата ответа.

Когда нужен резервный канал

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

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

Какие метрики показывают качество каскада

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

Метрики нужно смотреть вместе с расчётом TPS и очередей и нормализованными DLR. Высокая общая доставляемость может скрывать поздние OTP или постоянную работу на дорогом резервном маршруте.

Как испытать схему до аварии

Тестовый план должен включать не только полное отключение API:

  • отказ DNS и TCP-соединения;
  • медленный ответ после фактического принятия сообщения;
  • ограничение TPS;
  • серия явных отказов submit;
  • задержка и нарушение порядка DLR;
  • недоступность хранилища идемпотентности;
  • восстановление маршрута после circuit breaker;
  • исчерпание TTL при большой очереди;
  • несовместимое имя отправителя на резервном пути.

Результат теста — журнал времени переключения, число сообщений в неопределённом состоянии, подтверждённые дубли и влияние на приоритетный трафик. Общая практика устойчивости внешних API помогает оформить тайм-ауты, retry и circuit breaker как единую политику.

Чек-лист промышленного запуска

  • определить стабильный ключ идемпотентности бизнес-события;
  • нормализовать результаты submit и финальные DLR;
  • описать состояние unknown и процедуру сверки;
  • задать TTL и максимум попыток для каждого класса сообщений;
  • проверить имя отправителя и ограничения каждого маршрута;
  • разделить повтор на маршруте и переход к следующему;
  • настроить circuit breaker с ограниченным возвратом;
  • изолировать OTP от массового трафика;
  • включить метрики дублей, задержки и стоимости;
  • провести управляемый тест деградации;
  • документировать ручное отключение и возврат маршрута;
  • регулярно сверять статусы и биллинг с поставщиками.

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

SMSA2PИнфраструктураУведомления

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