Коротко. Очередь растёт по трём причинам: нет обработчика, медленный обработчик, брокер заблокировал приём. Первое видно по consumers, второе по базе, третье по alarm. Два алерта, нет потребителей и непрерывный рост, закрывают проблему до того, как её заметят пользователи.

Пользователи жалуются, что задания «висят», уведомления приходят с опозданием на час, документ отправлен по регламенту и пропал. Сервисы RX при этом запущены, база отвечает, диски не полные. Чаще всего в этот момент в RabbitMQ растёт одна очередь, а её обработчик либо отвалился, либо не успевает. Разбираем, как это увидеть, что сделать и как больше не узнавать об этом от пользователей.

Симптом

Для пользователей: задачи не переходят между этапами, задания не появляются у исполнителя, уведомления и почтовые рассылки задерживаются, фоновые операции «в обработке» бесконечно. Обычно страдает не всё сразу, а один тип операций.

Для администратора: в панели управления RabbitMQ у одной или нескольких очередей растёт колонка Ready, а колонка Consumers равна нулю или обработчики есть, но Unacked стоит на месте. В логах сервиса-обработчика повторяются ошибки подключения к брокеру или одна и та же ошибка при разборе сообщения.

Почему так

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

  1. Обработчика нет. Сервис упал, не смог подключиться к брокеру после перезапуска, у учётной записи нет прав на виртуальный хост, истёк сертификат при TLS-подключении. Очередь копится, Consumers = 0.
  2. Обработчик есть, но медленный. Каждое сообщение упирается в базу: долгий запрос, блокировка, ожидание внешней системы. Consumers > 0, Unacked небольшой и постоянный, Ready растёт.
  3. Брокер сам остановил приём. RabbitMQ включил защиту по памяти или диску и заблокировал публикующие соединения. Растёт всё сразу, а в панели горит alarm.

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

Диагностика

Первые пять минут, без панели управления:

# самые большие очереди и число обработчиков у каждой
rabbitmqctl list_queues name messages messages_ready messages_unacknowledged consumers | sort -k2 -n -r | head -15

# включена ли защита брокера по памяти или диску
rabbitmqctl status | grep -A3 -i alarm

# сколько всего очередей: тысячи на небольшой инсталляции это уже утечка
rabbitmqctl list_queues name | wc -l
Что видим Что это значит Куда идти дальше
consumers = 0 у рабочей очереди обработчик не подключён логи сервиса, который должен её читать; права пользователя брокера; сертификат
consumers > 0, ready растёт обработчик не успевает база: активные запросы и блокировки; логи обработчика на повторяющуюся ошибку
активен alarm по диску или памяти брокер заблокировал публикацию место на диске брокера, порог disk_free_limit, порог памяти
тысячи очередей с нулём сообщений утечка временных очередей политика с автоудалением, см. ниже

Если сервис пишет в лог одну и ту же ошибку на каждое сообщение, это «ядовитое» сообщение: оно возвращается в очередь и блокирует всё за собой. Его нужно посмотреть в панели управления (Get messages без удаления) и отдать разработчикам или вендору вместе с текстом ошибки.

Что сделать

Снять симптом. Если обработчика нет, перезапустить сервис и убедиться, что он подключился: число consumers стало больше нуля и ready начал падать. Если горит alarm по диску, освободить место или поднять свободный объём, а не снижать порог: порог защищает данные брокера.

Убрать причину.

  • Проверить, что порог disk_free_limit меньше реального свободного места на диске брокера. Классическая ошибка: диск под данные брокера выделен маленький, а порог по умолчанию больше этого диска целиком. Alarm тогда не снимается никогда, а брокер считает, что всё в порядке.
  • Для медленного обработчика найти запрос, в который он упирается: в PostgreSQL это pg_stat_activity с сортировкой по длительности и pg_locks на предмет ожиданий. Дальше это фактура для разработчиков прикладной части или вендора.
  • Для утечки временных очередей завести политику брокера с параметром expires для очередей по шаблону имени: очередь без потребителей удаляется сама через заданное время. Рабочие очереди сервисов под шаблон попадать не должны, поэтому шаблон проверяют на живом списке очередей, а не пишут наугад.

Узнавать первыми. Два правила алертинга, которых достаточно на первое время, словами:

  1. У рабочей очереди нет потребителей дольше пяти минут. Это всегда авария, ложных срабатываний почти нет.
  2. Число сообщений в очереди растёт непрерывно последние десять минут. Порог по абсолютному числу подбирается под инсталляцию, а вот рост как таковой одинаково плох везде.

Третьим добавляют активен alarm брокера и число очередей выросло на порядок за сутки.

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

Чего не делать

  • Очищать очередь, не глядя. В ней могут быть задания пользователей и результаты интеграций. Сначала посмотреть, что внутри, и понять, почему не обрабатывается.
  • Перезапускать брокер как первое действие. Обработчик, который не подключался из-за прав или сертификата, не подключится и после перезапуска, а сообщения в памяти могут быть потеряны.
  • Поднимать пороги памяти и диска, чтобы погасить alarm. Alarm сигналит о реальной нехватке ресурса. Порог трогают только когда он заведомо неверный, как в примере с диском выше.
  • Считать, что «очередь ноль» значит «всё хорошо». Очередь ноль при нуле потребителей означает, что никто ничего не публикует, и это тоже повод разобраться.