RabbitMQ — отличный брокер распределенных сообщений, но его не так просто администрировать программно. В этом уроке я покажу вам, как создать кластер, добавить узлы, удалить узлы, запускать и останавливать. В качестве бонуса я поделюсь файлом Fabric, который позволит вам получить полный контроль. Код доступен на GitHub .
Краткое введение в RabbitMQ
RabbitMQ — очень популярная очередь сообщений. У вас может быть несколько производителей, отправляющих сообщения, и потребители могут использовать эти сообщения полностью отделенным образом. RabbitMQ очень популярен по нескольким причинам:
- Это быстро и надежно.
- Это открытый исходный код , но есть коммерческая поддержка, если вы этого хотите.
- Он работает в вашей операционной системе.
- Это активно развивается.
- Это проверено в бою.
RabbitMQ реализован на Erlang, что немного необычно, но одна из причин, по которой он так надежен.
Предпосылки
В этом уроке я буду использовать локальный кластер Vagrant из трех узлов. Если у вас уже есть три доступные машины (виртуальные или нет), вы можете использовать их вместо. Обратите внимание на порты и сети.
Установите VirtualBox
Следуйте инструкциям по установке VirtualBox.
Установить Vagrant
Следуйте инструкциям по установке Vagrant
Создать кластер RabbitMQ
Вот Vagrantfile, который создаст локальный кластер из трех узлов на вашем компьютере. ОС Ubuntu 14.04 (Trusty).
ruby # -*- mode: ruby -*- # vi: set ft=ruby : hosts = { "rabbit-1" => "192.168.77.10", "rabbit-2" => "192.168.77.11", "rabbit-3" => "192.168.77.12" } Vagrant.configure("2") do |config| config.vm.box = "trusty64" hosts.each_with_index do |(name, ip), i| rmq_port = 5672 + i admin_port = 15672 + i config.vm.define name do |machine| machine.vm.network :private_network, ip: ip config.vm.hostname = "rabbit-%d" % [i + 1] config.vm.network :forwarded_port, guest: 5672, guest_ip: ip, host: rmq_port config.vm.network :forwarded_port, guest: 15672, guest_ip: ip, host: admin_port machine.vm.provider "virtualbox" do |v| v.name = name end end end end
Чтобы создать пустой кластер, введите: vagrant up
.
Настройка SSH
Чтобы облегчить ssh в узлы кластера, введите: vagrant ssh-config >> ~/.ssh/config
.
Если вы наберете: cat ~/.ssh/config
, вы должны увидеть записи для rabbit-1, rabbit-2 и rabbit-3.
Теперь вы можете использовать ssh на каждой виртуальной машине по имени: ssh rabbit-1
.
Убедитесь, что узлы достижимы по имени
Самый простой способ — отредактировать файл / etc / hosts. Например, для кролика-1 добавьте адреса кролика-2 и кролика-3.
plain 192.168.77.11 rabbit-2 192.168.77.12 rabbit-3
Повторите процесс для всех узлов.
Установить RabbitMQ
Я буду использовать apt-get здесь для операционных систем Debian / Ubuntu. Если ваш кластер работает в другой ОС, следуйте инструкциям на странице установки RabbitMQ .
Обратите внимание, что иногда довольно устаревшая версия RabbitMQ доступна по умолчанию. Если вы хотите установить самую последнюю версию, вы можете загрузить пакет .deb напрямую или добавить apt-репозиторий RabbitMQ, используя эти инструкции .
Текущая версия RabbitMQ для Ubuntu 14.04 — 3.2, что достаточно для наших целей. Убедитесь сами, набрав: apt-cache show rabbitmq-server
.
Давайте продолжим и установим его на каждую машину:
plain sudo apt-get update sudo apt-get install rabbitmq-server -y
Не стесняйтесь использовать ваши любимые инструменты управления конфигурацией, такие как Chef или Ansible, если вы предпочитаете.
Обратите внимание, что Erlang будет установлен первым в качестве предварительного условия.
Включить плагин управления RabbitMQ
Плагин управления действительно классный. Он предоставляет вам API на основе HTTP, а также веб-интерфейс и инструмент командной строки для управления кластером. Вот как это сделать:
plain sudo rabbitmq-plugins enable rabbitmq_management
Получить инструмент командной строки управления
Загрузите его с http://192.168.77.10:15672/cli/rabbitmqadmin. Обратите внимание, что документация RabbitMQ неверна и требует загрузки с http: //
Это HTTP-клиент на основе Python для API-интерфейса управления RabbitMQ. Это очень удобно для сценариев кластеров RabbitMQ.
Основные понятия RabbitMQ
RabbitMQ реализует стандарт AMQP 0.9.1 (расширенный протокол очереди сообщений) . Обратите внимание, что уже существует стандарт AMQP 1.0, и RabbitMQ имеет плагин для его поддержки, но он считается прототипом из-за недостаточного использования в реальных условиях.
В модели AMQP издатели отправляют сообщения посреднику сообщений (в данном случае RabbitMQ — посредник сообщений) через обмен. Посредник сообщений распределяет сообщения в очереди на основе метаданных, связанных с сообщением. Потребители потребляют сообщения из очередей. Сообщения могут быть или не быть подтверждены. RabbitMQ поддерживает множество моделей программирования на основе этих концепций, таких как рабочие очереди, публикация-подписка и RPC.
Управление вашим кластером
Для управления кластером используются три сценария. Скрипт rabbitmq-server запускает сервер RabbitMQ (запускает его). Rabbitmqctl используется для управления кластером (остановка, сброс, объединение узлов кластера и получение статуса). Rabbitmqadmin, который вы скачали ранее, используется для настройки и администрирования кластера (объявление vhosts, пользователей, обменов и очередей). Создание кластера включает в себя только rabbitmq-server и rabbitmqctl.
Во-первых, давайте запустим rabbitmq-сервер как сервис (демон) на каждом из наших хостов rabbit-1, rabbit-2 и rabbit-3.
plain sudo service rabbitmq-server start
Это запустит и Erlang VM, и приложение RabbitMQ, если узел не работает. Чтобы убедиться, что он работает правильно, введите:
plain sudo rabbitmqctl cluster_status
Выход должен быть (для кролика-1):
plain Cluster status of node 'rabbit@rabbit-1' ... [{nodes,[{disc,['rabbit@rabbit-1']}]}, {running_nodes,['rabbit@rabbit-1']}, {partitions,[]}] ...done.
Это означает, что узел еще не кластеризован ни с какими другими узлами и является дисковым узлом. Он также работает, как вы можете видеть, что он появляется в списке running_nodes.
Чтобы остановить сервер, введите следующую команду:
plain sudo rabbitmqctl stop_app
Затем, если вы проверите состояние кластера:
plain sudo rabbitmqctl cluster_status
Выход должен быть:
plain Cluster status of node 'rabbit@rabbit-1' ... [{nodes,[{disc,['rabbit@rabbit-1']}]}] ...done.
Больше нет работающих узлов.
Вы можете повторить процесс для других узлов (кролик-2 и кролик-3) и увидеть, что они знают только себя.
Эрланг печенье
Прежде чем вы сможете создать кластер, все узлы в кластере должны иметь один и тот же файл cookie. Файл cookie — это файл, который среда выполнения Erlang использует для идентификации узлов. Он находится в /var/lib/rabbitmq/.erlang.cookie. Просто скопируйте содержимое с кролика-1 на кролика-2 и кролика-3.
Узлы кластеризации вместе
Чтобы сгруппировать эти отдельные узлы в единый кластер, требуется определенная работа. Вот процедура:
- Работает один узел (например, кролик-1).
- Остановите другой узел (например, кролика-2).
- Сброс остановленного узла (кролик-2).
- Кластеризация другого узла в корневой узел.
- Запустите остановленный узел.
Давай сделаем это. ssh into rabbit-2 и выполните следующие команды:
plain sudo rabbitmqctl stop_app sudo rabbitmqctl reset sudo rabbitmqctl join_cluster rabbit@rabbit-1
Теперь введите: sudo rabbitmqctl cluster_status
.
Выход должен быть:
« `обычный статус кластера узла ‘rabbit @ rabbit-2’… [{узлов, [{disc, [‘rabbit @ rabbit-1’, ‘rabbit @ rabbit-2’]}]}]… Готово. Как видите, оба узла теперь кластеризованы. Если вы повторите это на rabbit-1, вы получите следующий вывод:
Кластерный статус узла "кролик @ кролик-1" ... [{Узлы, [{диск, [ 'кролика @ кролика-1', 'кролик @ кролика-2']}]}, {Running_nodes, [ 'кролика @ кролика-1']}, {Перегородки, []}] ...сделано. `` `
Теперь вы можете начать Кролик-2.
plain sudo rabbitmqctl start_app
Если вы проверите статус снова, оба узла будут работать:
plain Cluster status of node 'rabbit@rabbit-2' ... [{nodes,[{disc,['rabbit@rabbit-1','rabbit@rabbit-2']}]}, {running_nodes,['rabbit@rabbit-1','rabbit@rabbit-2']}, {partitions,[]}] ...done.
Обратите внимание, что оба узла являются узлами диска, что означает, что они хранят свои метаданные на диске. Давайте добавим кролика-3 в качестве узла оперативной памяти. ssh to rabbit-3 и выполните следующие команды:
plain sudo rabbitmqctl stop_app sudo rabbitmqctl reset sudo rabbitmqctl join_cluster --ram rabbit@rabbit-2 sudo rabbitmqctl start_app
Проверка статуса показывает:
plain Cluster status of node 'rabbit@rabbit-3' ... [{nodes,[{disc,['rabbit@rabbit-2','rabbit@rabbit-1']}, {ram,['rabbit@rabbit-3']}]}, {running_nodes,['rabbit@rabbit-1','rabbit@rabbit-2','rabbit@rabbit-3']}, {partitions,[]}] ...done.
Все узлы кластера работают. Узлы диска — это кролик-1 и кролик-2, а узел ОЗУ — кролик-3.
Поздравляем! У вас есть работающий кластер RabbitMQ.
Реальные осложнения
Что произойдет, если вы захотите изменить конфигурацию своего кластера? Вам придется использовать хирургическую точность при добавлении и удалении узлов из кластера.
Что произойдет, если узел еще не перезапущен, но вы пытаетесь продолжить с помощью stop_app
, reset
и start_app
? Что ж, команда stop_app якобы будет успешной и вернет «готово», даже если целевой узел не работает. Однако последующая команда сброса не удастся с неприятным сообщением. Я потратил много времени на то, чтобы почесать голову, пытаясь понять это, поскольку предполагал, что проблема заключается в каком-то параметре конфигурации, который влияет только на сброс.
Другой недостаток заключается в том, что если вы хотите сбросить последний узел диска, вы должны использовать force_reset
. Попытка выяснить в общем случае, какой узел был последним узлом диска, не тривиальна.
RabbitMQ также поддерживает кластеризацию через файлы конфигурации. Это замечательно, когда ваши дисковые узлы работают, потому что перезапущенные узлы ОЗУ будут просто кластеризоваться на основе файла конфигурации без необходимости их явной кластеризации. Опять же, он не летает, когда вы пытаетесь восстановить сломанный кластер.
Надежная кластеризация RabbitMQ
Это сводится к следующему: вы не знаете, какой последний узел диска вышел из строя. Вы не знаете метаданные кластеризации каждого узла (может быть, он сбился при выполнении сброса). Чтобы запустить все узлы, я использую следующий алгоритм:
- Запустите все узлы (по крайней мере, последний узел диска должен быть в состоянии начать).
- Если даже ни один узел не может запуститься, значит, у вас все в порядке. Просто выручите.
- Отслеживайте все узлы, которые не удалось запустить.
- Попробуйте запустить все неисправные узлы.
- Если некоторые узлы не удалось запустить во второй раз, вы попали. Просто выручите.
Этот алгоритм будет работать до тех пор, пока ваш последний узел диска физически исправен.
После того, как все узлы кластера подключены, вы можете переконфигурировать их (помните, что вы не уверены, что такое метаданные кластеризации каждого узла). Ключ заключается в принудительном сбросе каждого узла. Это гарантирует, что любой след предыдущей конфигурации кластера будет удален со всех узлов. Сначала сделайте это для одного узла диска:
plain stop_app force_reset start_app
Затем для каждого другого узла (диска или ОЗУ):
plain stop_app force_reset join_cluster [list of disc nodes] start_app
Удаленное управление кластером
Вы можете ввести SSH в каждый ящик и выполнить вышеупомянутые шаги для каждого ящика вручную. Это работает, но очень быстро стареет. Кроме того, это нецелесообразно, если вы хотите построить и разрушить кластер как часть автоматизированного теста.
Одним из решений является использование ткани . Одна серьезная ошибка, с которой я столкнулся, заключается в том, что когда я выполнял алгоритм кластера сборки вручную, он работал отлично, но когда я использовал Fabric, он таинственным образом не работал. После некоторой отладки я заметил, что узлы запустились успешно, но к тому времени, когда я попытался stop_app, узлы были недоступны. Это оказалось ошибкой новичка из ткани с моей стороны. Когда вы запускаете удаленную команду с помощью Fabric, она запускает новую оболочку на удаленном компьютере. Когда команда завершена, оболочка закрывается, отправляя сигнал SIGHUP (сигнал зависания) всем его подпроцессам, включая узел Erlang. Использование nohup позаботится об этом. Другой более надежный вариант — запуск RabbitMQ в качестве службы (демон).
Администрирование кластера программно
Администрирование означает создание виртуальных хостов, пользователей, бирж и очередей, настройку разрешений и привязку очередей к биржам. Первое, что вы должны сделать, если вы еще этого не сделали, это установить плагины управления. Я не уверен, почему вы должны включить его самостоятельно. Это должно быть включено по умолчанию.
Веб-интерфейс фантастический, и вы должны обязательно ознакомиться с ним. Однако для удаленного администрирования кластера можно использовать API-интерфейс управления RESTful. Существует также инструмент командной строки Python с именем rabbitmqadmin, для которого требуется Python 2.6+. Использовать rabbitmqadmin довольно просто. Единственная проблема, которую я обнаружил, это то, что я мог использовать только гостевую учетную запись по умолчанию для администрирования кластера. Я создал другого пользователя-администратора с именем «admin», установил его разрешения для всех (настройка / чтение / запись) и дал ему тег «administrator» (дополнительное требование API управления), но я продолжал получать ошибки разрешения.
Проект Elmer позволяет вам указать конфигурацию кластера как структуру данных Python (см. Sample_config.py) и настроит все для вас.
Взять домой очки
- RabbitMQ это круто.
- История администратора кластера не герметична.
- Программное администрирование является ключевым.
- Fabric — это замечательный инструмент для удаленного управления несколькими Unix-системами.