RabbitMQ в dBrain: опыт внедрения в платформу контейнеризации

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

a312a97d6dbaf325d0bc75d238b94b52.png

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

Что такое брокер RabbitMQ

RabbitMQ — один из самых популярных брокеров сообщений наряду с Kafka. Kafka построена по принципу «глупый брокер, умный потребитель», RabbitMQ — «умный брокер, глупый потребитель». В RabbitMQ можно строить логику обработки и направления сообщений, в то время как Kafka — это просто лог данных, а вся логика хранится в консьюмерах. Kafka обычно используется с большим потоком сообщений или данных, например, десятки или сотни тысяч сообщений в секунду. Если в приложении не планируется обрабатывать такие объемы, то стоит рассмотреть RabbitMQ: он более легковесный в потреблении ресурсов и проще в настройке. У каждого брокера есть плюсы и минусы, оба используют в крупных компаниях.

В dBrain мы используем оба брокера, чтобы закрывать потребности компаний любого размера и запросов к функционалу MQ (Message queue).

Как реализовали в dBrain

В платформе dBrain предусмотрен инструмент для создания и развертывания приложений, управления базами данных и мониторинга — консоль. Это веб-интерфейс, который упрощает взаимодействие с инфраструктурой, базами данных, Kubernetes. Из консоли dBrain в пару кликов можно развернуть любой сервис (как это происходит, можно прочитать тут). Брокер RabbitMQ также можно развернуть с помощью интерфейса dBrain.

2f13c9e4728e3e3412bab1124c974fb1.png

В dBrain мы реализовали управление RabbitMQ на основе двух популярных операторов:

Первый управляет непосредственно кластерами RabbitMQ, второй — всеми остальными элементами в кластере, такими как User, Vhost, Queue, Exchange, Binding и тд.

Проблемы внедрения

При внедрении брокера в платформу контейнеризации dBrain возникли некоторые нюансы. Например, проблема с дефолтными настройками RabbitMQ Cluster: сервис не утилизировал (не использовал по максимуму) всю выделенную RAM (random-access memory).

Для этого мы обратились к настройке vm_memory_high_watermark, она по дефолту равна 40%. На первом шаге попробовали заменить настройку на vm_memory_high_watermark.relative = 0.7 (согласно рекомендациям). Это улучшило утилизацию, но привело к периодическому рестарту подов. После более детального изучения документации мы изменили настройку как рекомендовано тут и тут, немного скорректировав логику расчета: vm_memory_high_watermark.absolute = {{ (memory * 0.7) | int }}Mi.Операция приведения к int обязательна, т.к. RabbitMQ не запустится, если указать не целое число.

Для продакшен-окружения рекомендуем установить настройку disk_free_limit.relative = 1.0 чтобы RabbitMQ мог сбросить все содержимое из памяти на диск. Также стоит выбрать настройку cluster_partition_handling. Если у вас нечетное количество инстансов, рекомендуем выставить в pause_minority.

94da34c7c5650da8b6657b31c577e23b.png

Настройка RabbitMQ включает несколько уровней:

  • rabbitmq.conf — основной файл настроек, самый удобный и простой:

  • advanced.config — конфиг в формате Erlang-а: ограниченный набор настроек, используется, когда не подошел пункт 1

  • rabbitmq-env.conf — файл для настроек переменных окружения

Дополнительный функционал в RabbitMQ подключается через набор плагинов. Список предустановленных плагинов можно проверить, выполнив в поде команду rabbitmq-plugins list. Там же можно увидеть список включенных плагинов. Мы дополнительно включили плагин rabbitmq_top, который предоставляет простой, но информативный UI. Он нужен, когда необходимо посмотреть детальную информацию.

Самый простой способ включения настроек для мониторинга в RabbitMQ реализован аналогично — через плагин rabbitmq_prometheus. Он открывает порт и предоставляет метрики в формате prometheus. Далее по набору лейблов на поде RabbitMQ через указанный для мониторинга порт VictoriaMetrics забирает метрики согласно описанию ниже.

apiVersion: operator.victoriametrics.com/v1beta1
kind: VMPodScrape
metadata:
  name: rabbitmq-metrics
  namespace: mon
  labels:
    component: rabbitmq
spec:
  podTargetLabels:
    - "cluster-name"
  namespaceSelector:
    any: true
  selector:
    matchLabels:
      component: rabbitmq
      app.kubernetes.io/part-of: rabbitmq
      database-metrics-enabled: true
  podMetricsEndpoints:
    - port: prometheus
      path: /metrics

Подобный пример из оператора тут (как и пример алертов для RabbitMQ).

Помимо самого кластера RabbitMQ в dBrain можно управлять внутренними элементами кластера, такими как Vhost, User, Queue, Binding, Exchange.

Для примера создадим в кластере эти сущности (все настройки можно найти тут):

apiVersion: rabbitmq.com/v1beta1
kind: Vhost
metadata:
  name: rabbitmq-cluster1-vhost-host1
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  name: host1
  tracing: false
  defaultQueueType: classic
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
  name: rabbitmq-cluster1-queue-queue1
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  name: queue1
  vhost: host1
  type: classic
  autoDelete: false
  durable: true
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend
apiVersion: rabbitmq.com/v1beta1
kind: Exchange
metadata:
  name: rabbitmq-cluster1-exchange-exchange1
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  name: exchange1
  vhost: host1
  type: direct
  autoDelete: false
  durable: true
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend
apiVersion: rabbitmq.com/v1beta1
kind: Binding
metadata:
  name: rabbitmq-cluster1-binding-queue1-to-exchange1-xyz
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  vhost: host1
  source: queue1
  destination: exchange1
  destinationType: exchange
  routingKey: "product.*"
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend

Создадим юзера, креды и права в кластере:

58f860792c79a2d18b2e56292537365e.png

apiVersion: v1
kind: Secret
metadata:
  name: rabbitmq-cluster1-user1
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
type: Opaque
stringData:
  username: user1
  password: secret_password
apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
  name: rabbitmq-cluster1-user1
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend
  importCredentialsSecret:
    name: rabbitmq-cluster1-user1
apiVersion: rabbitmq.com/v1beta1
kind: Permission
metadata:
  name: rabbitmq-cluster1-user1-permission-yxz
  namespace: backend
  labels:
    app: rabbitmq-cluster1
    component: rabbitmq
    cluster-name: cluster1
spec:
  vhost: host1
  user: user1
  permissions:
    write: "*"
    configure: "*"
    read: "*"
  rabbitmqClusterReference:
    name: rabbitmq-cluster1
    namespace: backend

178bd115fdf67ea2f89ca7c85ac27767.png

Если в будущем потребуется изменить пароль пользователя, то просто поменять значения в Secret для этого юзера будет недостаточно. Существует важный нюанс: оператор не отслеживает изменения в Secret’ах. Чтобы оператор смог увидеть новое значение и обновить пароль в RabbitMQ, необходимо модифицировать содержимое лейблов или аннотаций в User.

Вывод

Внедрение RabbitMQ в dBrain — это развитие функционала платформы в соответствии запросами клиентов, которые хотят видеть альтернативу Kafka. Основные функции управления RabbitMQ доступны через пользовательский интерфейс dBrain. В редких случаях, когда требуются специфические изменения, можно воспользоваться YAML-конфигурациями. Добавление сервиса в dBrain упрощает запуск и управление RabbitMQ для приложений и сокращает время от начала разработки до выхода продукта на рынок.

Делитесь в комментариях какими брокерами сообщений вы пользуетесь и какие темы в разработке вам интересны.

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

© Habrahabr.ru