Почему очередь Azure Service Bus теряет сообщения при пиках
На пике нагрузки очередь Azure Service Bus ведёт себя иначе, чем на тестовом контуре: глубина растёт быстрее, чем потребители разбирают сообщения, и потеря сообщений проявляется не сразу. Сначала это задержка обработки, потом рост числа попыток доставки, потом мёртвая очередь. Причина почти никогда не в самом брокере — складываются лимиты подписки, отсутствие ограничения параллелизма у потребителя и слишком короткое время жизни сообщения.
Дальше включается каскад: сообщение не подтверждается вовремя, блокировка истекает, брокер отдаёт его повторно, и обработчик запускает ту же операцию второй раз. Повторная доставка превращается в дубли списаний, пока дежурный разбирает инцидент руками. Часть сообщений при этом уходит в мёртвую очередь, часть истекает по времени жизни — восстановить их уже нечем.
Цена сбоя — не только простой обмена. Каждый инцидент разбирается вручную: поднять метрики, сопоставить идентификаторы, найти шаг, на котором потерялось сообщение, доставить его повторно и при этом не задвоить операцию. Если права на очередь выданы широко, добавляется риск: любой сервис может читать и удалять чужое.
Поэтому начинаем не с настроек, а с разбора потока: где сообщение может потеряться, какие повторы безопасны, чем ограничен потребитель на пике и по какому признаку дежурный понимает, что пора вмешаться. Ниже — как это закрывается.
Что даёт управляемая шина: устойчивость и наблюдаемость
Управляемая шина Azure Service Bus снимает целый класс отказов интеграции за счёт подтверждений доставки и повторных попыток с нарастающей паузой. Сообщение покидает очередь только после успешной обработки, а при исчерпании попыток уходит в очередь недоставленных с кодом причины. Дубли отсекаются ключом идемпотентности на стороне потребителя — повторный запуск после сбоя не порождает вторых заказов и списаний.
Наблюдаемость строится на метриках самой шины: длина очереди, возраст самого старого сообщения, число повторных попыток, доля срабатываний предохранителя. Сквозной идентификатор связывает запись в шине с обработкой в сервисе, поэтому инцидент разбирается по журналу, а не по разрозненным логам приложений. Алерт ставим на рост очереди недоставленных — дежурный узнаёт о проблеме раньше, чем её замечает бизнес.
Доступ разводится по ролям: отправители только пишут, потребители только читают, разбор недоставленных — отдельная роль для дежурного. Ключи живут в хранилище секретов и ротируются, прямые строки подключения в конфигурации сервисов не остаются.
Нагрузочный профиль прогоняем до продакшена: пиковая подача, отказ одного потребителя, длительная задержка обработки. После такого прогона время восстановления после сбоя считается минутами, доля потерянных сообщений по подтверждённым отправкам — нулевой, а объём ручных разборов падает до единиц в неделю.
Режимы доставки и топологии очередей
Топология очереди определяет не только маршрут сообщения, но и то, как система поведёт себя при сбое. Неверно выбранный режим доставки проявляется только под нагрузкой: дубли заказов, потерянное событие, застрявшая очередь разгрузки. Ниже — варианты, между которыми реально выбирают при проектировании обмена.
Варианты обмена и их ограничения
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Очередь «точка-точка» | один производитель — один потребитель: команды, задания на обработку | конкурирующие потребители не сохраняют порядок по бизнес-ключу |
| Тема с несколькими подписками | событие должно независимо уйти нескольким системам | каждая подписка хранит свою копию, объём растёт линейно по числу потребителей |
| Сессии | строгий порядок в рамках ключа: один заказ, один счёт | сессию обрабатывает один потребитель — параллелизм ниже |
| Дедупликация | источник повторяет отправку при своём сбое | окно хранения ключа ограничено, а ключ нужно задавать явно |
| Автопересылка | разгрузка входной очереди и маршрутизация по признаку | цепочка скрывает путь сообщения, усложняет разбор инцидентов |
Режимы комбинируются: сессии поверх подписок дают порядок по ключу и независимых потребителей, а дедупликация вместе с автопересылкой закрывает повторную доставку на стыке сервисов. Важно, что каждое сочетание меняет и профиль нагрузки — число одновременных обработчиков, время жизни сообщения, порог ухода в очередь недоставленных.
Мы фиксируем выбранную топологию в схеме обмена и в настройках, чтобы поведение при сбое было предсказуемым. На платформе Azure Service Bus эти режимы задаются декларативно, поэтому схема остаётся воспроизводимой между средами.
Внедрение: от аудита до передачи в эксплуатацию
До правок в рабочем контуре мы фиксируем текущее состояние обмена сообщениями: кто публикует, кто читает, где сообщения теряются или обрабатываются дважды. Аудит интеграции даёт карту потоков и перечень узких мест, поэтому каждая следующая ступень опирается на проверенные данные, а не на предположения.
- Аудит интеграции. Разбираем издателей и подписчиков, темы и очереди Azure Service Bus, клиентские повторы и участки без защиты от дублей. На выходе — схема потоков с временем обработки и объёмом сообщений, ушедших в отложенные.
- Проектирование схемы. Раскладываем нагрузку по очередям и подпискам, задаём правила повторной доставки, время жизни сообщения и отсечение дублей.
- Настройка очередей и доступов. Создаём сущности, настраиваем разделение прав между сервисами и людьми: каждый получает ровно те операции, которые ему нужны.
- Нагрузочная проверка. Прогоняем пиковый поток и сценарии отказа: недоступный подписчик, медленная обработка, рост очереди. Смотрим, восстанавливается ли система сама и за какое время.
- Регламент эксплуатации. Описываем пороги срабатывания, действия дежурного, порядок вывода сообщений из отложенных и правила изменения настроек.
- Передача в поддержку. Проводим разбор схемы с вашей командой, отдаём документацию и остаёмся на связи на период первых изменений.
Политики доступа, роли и регламенты: что передаём
На выходе заказчик получает не «настроенную очередь», а комплект, по которому сервис можно эксплуатировать, передать другой команде и пройти проверку безопасности. Для Azure Service Bus это особенно важно: доступ здесь выдаётся на уровне пространства имён и отдельных сущностей, и без явного регламента права расползаются за пару месяцев. Ниже — минимальный набор артефактов, который передаём вместе с работающей шиной.
- Политики доступа — отдельная политика на отправку, приём и управление для каждого сервиса вместо одного общего ключа на всё окружение.
- Роли и ключи — привязка сервисов через управляемые удостоверения, где это поддерживается; там, где нет — ключ с указанием владельца, срока ротации и порядка отзыва.
- Разграничение прав — матрица «сервис → очередь или топик → разрешённые операции», по которой видно, кто и куда может писать или читать.
- Схема потоков сообщений — отправители, подписчики, правила фильтрации, обработка повторов и очередь недоставленных сообщений.
- Описание сущностей — очереди, топики, подписки, время жизни сообщений, защита от дублей, режим сессий: всё с обоснованием выбранных значений.
- Документация — топология, правила именования, перечень владельцев сервисов и инструкция по подключению нового потребителя.
- Регламент обслуживания — периодичность ротации ключей, порядок вывода сервиса из доступа, разбор накопившихся недоставленных сообщений и пороги оповещений.
Такой пакет снимает главную проблему эксплуатации — когда шина работает, но никто не знает, какие права кому выданы и что делать при отказе. Опишите вашу задачу — вернёмся с оценкой и планом работ.
Кейс: поток заказов под пиковой нагрузкой
До изменений весь поток заказов шёл через одну очередь Azure Service Bus: подписчиков было двое, а строку подключения с правами и на отправку, и на чтение выдавали в общий конфиг. В пик один из подписчиков падал, сообщения возвращались в очередь и обрабатывались повторно — покупатели получали по два одинаковых заказа, а дежурный инженер разбирал дубли руками. Восстановление после такого сбоя занимало до 40 минут, и понять причину было нечем: метрики очередей никто не снимал.
Что именно изменили
- Развели потоки: приоритетные заказы, фоновая аналитика и уведомления поехали в отдельные очереди со своими подписчиками и лимитами.
- Включили дедупликацию по идентификатору заказа и ограниченное число повторных попыток с переводом в очередь недоставленных сообщений.
- Заменили строку подключения на выдачу прав по ролям: у каждого сервиса только те операции, которые ему нужны.
- Настроили оповещения на длину очереди, возраст старейшего сообщения и долю записей в очереди недоставленных.
Что показали метрики
Доля дублей упала с 1,4% до 0,02% — повторная обработка перестала быть штатным сценарием. Время восстановления после падения подписчика сократилось с 40 минут до 4: сообщения остаются в очереди, пока сервис не вернётся. В пик очередь разбирается за считанные минуты, возраст старейшего сообщения не выходит за порог оповещения, а заказы, требующие ручного вмешательства, измеряются единицами в сутки вместо сотен.
Чем Service Bus отличается от самодельной очереди?
Самодельная очередь — это обычно таблица в базе и фоновый опрос по расписанию. Пока потребитель один и поток невелик, схема держится, но на втором обработчике появляются гонки за строку, двойная обработка и «залипшие» записи, которые никто не возвращает в работу.
Управляемая шина, например Azure Service Bus, закрывает доставку сама: подтверждение обработки, автоматический повтор при сбое, отдельная очередь неразобранных сообщений, порядок и защита от дублей. За вами остаётся идемпотентность самого обработчика — её не заменит ни один брокер.
Эксплуатационная нагрузка распределяется иначе: самодельную очередь вы обслуживаете целиком — чистка накопленного, миграции схемы, резервирование, дежурство. У шины это на стороне поставщика, а глубина очереди, число повторов и мёртвые письма видны в метриках, доступ к топикам раздаётся ролями через каталог.
Ограничения тоже есть: разделяемый сервис задаёт потолки на размер сообщения, число подписок и регион размещения. Выбор сведён в таблицу.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Очередь в своей базе | один потребитель, низкий поток, всё в одном контуре | нет гарантий доставки, повтор вручную, гонки за строку |
| Брокер на своих серверах | требования к размещению данных, нестандартные правила | отказоустойчивость и дежурство целиком на вас |
| Управляемая шина | несколько потребителей, нужны повторы, порядок, разбор недоставленных | лимиты разделяемого сервиса, зависимость от платформы |
Технические сомнения перед стартом работ
Перед стартом работ по очередям Azure Service Bus заказчики и их инженеры поднимают примерно один и тот же набор вопросов: как перейти без остановки сервисов, что делать с уже написанными потребителями и производителями, кто получит доступ и что увидит дежурный в момент сбоя. Ниже — короткие ответы, чтобы до оценки осталось меньше неизвестных.
Можно ли перевести очереди без остановки сервисов?
Да, миграция очередей идёт параллельным контуром: поднимаем новое пространство имён рядом с рабочим, включаем пересылку сообщений из старого в новое, переключаем потребителей по одному и держим прежний контур на откате согласованный срок. Приложение не останавливается — необработанные сообщения дожидаются переключения в очереди, повторная доставка гасится настройкой числа попыток и окна блокировки.
Придётся ли переписывать код под другую библиотеку?
Совместимость определяется протоколом обмена сообщениями, а не версией библиотеки в приложении. На практике меняются строка подключения, настройки повторных попыток и признак завершения сессии — логика обработки остаётся прежней. Полную переписку планируем только там, где сейчас используются самодельные обёртки поверх очередей.
Как выдаются доступы и где хранятся ключи?
Доступы выдаём через модель ролей с разделением прав на отправку, чтение и управление, отдельно на пространство имён и на конкретную очередь. Права получают сервисные учётные записи, а не люди: сотрудник уходит — доступ к очередям не меняется. Секреты живут в хранилище секретов и подставляются в среду выполнения, в репозитории и конфигурациях их нет.
Что видит дежурный и когда срабатывает оповещение?
Мониторинг строится на четырёх сигналах: длина очереди, возраст самого старого сообщения, доля сообщений в очереди необработанных и рост числа повторных доставок. По каждому задаём порог и время удержания, чтобы дежурство не поднимали из-за короткого всплеска. К оповещениям прикладываем инструкцию по разбору: где смотреть, что перезапустить, в каком случае звонить разработчику.
Обсудим задачу по вашим очередям
Оценка по очередям почти никогда не сводится к «поднимите нам Azure Service Bus»: объём работ определяется профилем нагрузки и требованиями к доставке. Чем точнее вводные на старте, тем меньше допущений в плане — и тем меньше переделок после первых прогонов под реальным трафиком.
Ниже — то, что стоит приложить к описанию задачи. Часть данных уже есть в мониторинге, часть достаточно оценить порядком величин:
- схема потоков: кто публикует сообщения, кто их читает, сколько нужно очередей и подписок, что уходит в отложенную обработку;
- профиль нагрузки: средняя и пиковая интенсивность, суточный и недельный ритм, допустимая задержка доставки в часы пик;
- требования к доставке: допустимы ли повторы, нужен ли строгий порядок обработки, через сколько неудачных попыток сообщение уходит в очередь необработанных;
- модель доступа: кто из сервисов и команд к каким сущностям обращается, нужны ли раздельные права на отправку и чтение;
- режим реагирования: куда уходят оповещения, кто смотрит на них в нерабочее время, какие пороги считать аварийными;
- текущее состояние и рамки: есть ли уже развёрнутые очереди, сколько сообщений накоплено, планируется ли перенос с другого брокера, как выкатываются конфигурации.
Дальше мы сверяем вводные с ограничениями платформы и возвращаемся с оценкой работ, составом этапов и сроками. Если каких-то данных нет — так и напишите: подскажем, как их снять или чем заменить, чтобы не тормозить старт.







