Статьи

RabbitMQ в нескольких зонах доступности AWS

При работе с AWS, чтобы иметь высокодоступную настройку, необходимо иметь экземпляры в более чем одной зоне доступности (AZ ≈ дата-центр). Если один AZ умирает (что может случиться), ваше приложение должно продолжать обслуживать запросы.

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

Во-первых (независимо от того, используете ли вы CloudFormation или ручную настройку), вы должны:

  • Есть VPC. Это может быть возможно без VPC, но я не могу этого гарантировать, особенно имена хостов DNS, как описано ниже
  • Объявите частные подсети (для каждого AZ)
  • Объявите группу автоматического масштабирования RabbitMQ (рекомендуется иметь одну) для охвата нескольких AZ, используя:
    1
    2
    3
    4
    5
    "AvailabilityZones" : {
              "Fn::GetAZs" : {
                "Ref": "AWS::Region"
              }
            }
  • Объявите группу автоматического масштабирования RabbitMQ, чтобы охватить несколько подсетей, используя свойство VPCZoneIdentifier
  • Объявите LoadBalancer перед вашими узлами RabbitMQ (это самый простой способ обеспечить равномерное распределение нагрузки на кластер Rabbit), чтобы охватить все подсети.
  • Объявить LoadBalancer как "CrossZone": true

Затем идет конкретная конфигурация RabbitMQ. Как правило, у вас есть два варианта:

Кластеризация не рекомендуется в случае WAN, но соединение между зонами доступности можно рассматривать (возможно, немного оптимистично) как локальную сеть (в этом подробном посте предполагается иное, но этот поток намекает на то, что использование кластера с несколькими AZ хорошо).

С помощью федерации вы объявляете свои биржи для отправки всех сообщений, которые они получают, на биржу другого узла. Это очень полезно в глобальной сети, где отключение от сети является обычным делом, а скорость не так важна. Но это все еще может быть применимо в сценарии с несколькими AZ, поэтому стоит исследовать. Вот пример с точными командами для выполнения, как этого добиться, используя плагин объединения . Сложной частью федерации является автоматическое масштабирование — всякий раз, когда вам нужно добавить новый узел, вы должны изменить (некоторые из) конфигурацию существующих узлов, чтобы установить новый узел в качестве восходящего. Вам также может понадобиться разрешить другим компьютерам подключаться в качестве гостя к rabbitmq ( [{rabbit, [{loopback_users, []}]}] в файле conf rabbitmq) или найти способ настроить пользовательскую пару имя пользователя / пароль для федерации работать.

С кластеризацией это немного по-другому, и на самом деле проще в настройке. Все, что вам нужно сделать, это написать скрипт для автоматического присоединения к кластеру при запуске. Это может быть сценарий оболочки или сценарий python, использующий AWS SDK. Основные шаги в таком сценарии (что, честно говоря, не так просто):

  • Найдите все запущенные экземпляры в группе автоматического масштабирования RabbitMQ (используя параметры фильтрации AWS API)
  • Если это первый узел (порядок случайный и не имеет значения), предположим, что это «начальный» узел для кластера, и все остальные узлы будут подключаться к нему
  • Если это не первый узел, подключитесь к первому узлу (используя rabbitmqctl join_cluster rabbit@{node} ), где {node} — это частное DNS-имя экземпляра (доступно через SDK)
  • Остановите RabbitMQ при выполнении всех настроек, запустите его после завершения

Во всех случаях (кластеризация или федерация) RabbitMQ использует доменные имена. Самый простой способ заставить его работать — включить DNS- "EnableDnsHostnames": true хостов в вашем VPC: "EnableDnsHostnames": true . Здесь есть небольшой взлом, когда речь идет о присоединении к кластеру — API AWS может вернуть полное доменное имя, которое включает в себя что-то вроде «.eu-west-1.compute.internal» в дополнение к ip-xxx-xxx -xxx-xxx часть. Поэтому, присоединяясь к кластеру RabbitMQ, вы должны удалить этот суффикс, иначе он не будет работать.

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

Сравнение двух подходов с PerfTest дает лучшую пропускную способность для опции кластеризации — с федерацией обрабатывалось примерно на 1/3 меньше сообщений, а также была немного большая задержка. Тесты должны выполняться от узла приложения к ELB RabbitMQ (в противном случае вы тестируете только один узел). Вы можете получить PerfTest и выполнить его примерно так (где адрес amqp — это DNS-имя балансировщика нагрузки RabbitMQ):

1
2
3
4
wget http://www.rabbitmq.com/releases/rabbitmq-java-client/v3.3.4/rabbitmq-java-client-bin-3.3.4.tar.gz
tar -xvf rabbitmq-java-client-bin-3.3.4.tar.gz
cd rabbitmq-java-client-bin-3.3.4
sudo sh runjava.sh com.rabbitmq.examples.PerfTest -x 10 -y 10 -z 10 -h amqp://internal-foo-RabbitMQEl-1GM6IW33O-1097824.eu-west-1.elb.amazonaws.com:5672

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