Как я перестал бояться очередей сообщений

14.11.2024 · 6 мин

Серверная стойка в дата-центре

Три года назад я относился к очередям сообщений с суеверным страхом. Казалось, что стоит только добавить в систему брокер — и вместо одной проблемы получаешь три: недоставленные сообщения, дублирование и загадочные зависания консьюмеров по пятницам вечером. Сейчас я понимаю, что боялся не самих очередей, а того, что не читал документацию дальше раздела «быстрый старт».

С чего всё началось

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

Разбираясь в проблеме, я впервые всерьёз прочитал про durable-очереди, publisher confirms и разницу между ack и nack. Оказалось, что половина «магии» брокера — это просто контракты, которые нужно соблюдать с обеих сторон: и у издателя, и у потребителя.

Три правила, которые я вывел для себя

Первое — сообщение должно быть идемпотентным по обработке, а не по отправке. Брокер может доставить одно и то же сообщение дважды, это нормальное поведение при at-least-once доставке. Если обработчик не умеет спокойно принять повтор, рано или поздно это аукнется.

Второе — размер очереди сам по себе не метрика. Важна скорость роста относительно скорости разбора. Я завёл алерт не на абсолютное число сообщений, а на производную — растёт ли очередь быстрее, чем мы успеваем её разгружать за последние пять минут.

Третье — dead letter queue нужна с первого дня, а не после первого инцидента. Сообщения, которые не удалось обработать после N попыток, должны куда-то деваться, иначе они либо теряются молча, либо блокируют очередь для всех остальных.

Что изменилось на практике

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

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

Что бы я посоветовал себе трёхлетней давности

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