RabbitMQ реализует расширение спецификации открытого стандарта AMQP 0.9.1 и используется в качестве основы для набора стандартов, управляющих всем процессом передачи сообщений.
Версия 0.9.1 была опубликована в ноябре 2008 г. и именно она будет рассмотрена в этом учебном пособии. AMQP — это двоичный протокол, подходящий для больших объемов данных. Он оптимизирован для эффективности и скорости машины, а не для удобства чтения человеком.
Другая ценная характеристика протокола AMQP заключается в том, что это стандарт с множественной реализацией, а это означает, что вы можете запускать AMQP с различными брокерами и другими приложениями.
AMQP определяет как протокол сетевого уровня, так и архитектуру высокого уровня для брокеров сообщений. Он определяет набор возможностей сообщений, которые должны быть доступны для реализации сервера, совместимого с AMQP. Сюда входят правила маршрутизации и хранения сообщений в брокере, чтобы следовать модели AMQ.
AMQP — это протокол прикладного уровня, который фокусируется на взаимодействии процессов между процессами в IP-сетях. Схема кодирования и набор процедур позволяют двум разным серверам взаимодействовать независимо от используемой технологии.
В целом, цель AMQP — обеспечить передачу сообщений через службы брокера через соединения TCP/IP. AMQP считается компактным протоколом, поскольку он двоичный. Это означает, что все, что отправляется через AMQP, представляет собой двоичные данные.
Соединения и каналы
В разговоре стороны приветствуют друг друга, обмениваются словесными подшучиваниями и в конечном итоге продолжают свой путь. Аналогичная форма связи происходит через соединения, открывающие облегченные каналы в RabbitMQ.
Соединение (Connection) — это связь между Клиентом и Брокером, которая выполняет основные сетевые задачи. Эти задачи включают первоначальную аутентификацию, разрешение IP и работу в сети. RabbitMQ поддерживает соединения IPv4 и IPv6. Также возможно шифровать соединения с помощью TLS.
Соединение может мультиплексироваться в несколько «облегченных соединений». Это «легкое соединение» называется Каналом (Channel). Каждое соединение может поддерживать набор базовых каналов. Службы обычно хотят иметь несколько подключений к брокеру, но вместо множества тяжелых подключений служба может повторно использовать ресурсы, создавая и удаляя каналы.
Канал повторно использует соединение, избавляя его от необходимости повторной авторизации и открытия нового TCP-потока. Каналы просто позволяют более эффективно использовать ресурсы. Каждая операция, связанная с протоколом AMQP, происходит по каналу.
Соединение создается путем открытия физического TCP-соединения с целевым сервером. Клиент разрешает имя хоста в один или несколько IP-адресов перед отправкой подтверждения. Затем принимающий сервер аутентифицирует клиента.
Чтобы отправить сообщение или управлять очередями, необходимо установить канал. Канал упаковывает сообщения и обрабатывает операции протокола. Клиенты отправляют сообщения через метод канала «basic_publish».
Создание и обслуживание очереди также отправляется через канал. Команды AMQP, такие как «queue.create» и «exchange.create», отправляются по каналу. Закрытие соединения закрывает все связанные каналы.
Канал можно открыть сразу после успешного открытия соединения.
Очереди (Queues)
Очередь — это место, где сообщения хранятся до тех пор, пока они не будут использованы потребителем или до тех пор, пока они не будут удалены из очереди другим способом. Очереди имеют свойства, определяющие их поведение, и эти свойства передаются брокеру при объявлении очереди.
- Очередь имеет некоторые обязательные свойства и некоторые необязательные. У очереди всегда есть имя, чтобы сервисы могли ссылаться на нее. Очереди, объявленной без имени, большинство клиентских библиотек присваивают случайное имя.
- Очередь может быть помечена как устойчивая, что указывает, должна ли очередь пережить перезапуск брокера.
- Очередь может быть эксклюзивной, что указывает, может ли очередь использоваться только одним соединением. Эксклюзивная очередь удаляется при закрытии соединения.
- Очередь также может быть объявлена со свойством auto-delete, что означает, что очередь, в которой был хотя бы один потребитель, удаляется, когда последний потребитель отписывается.\
- Существуют также некоторые дополнительные свойства, используемые плагинами и функциями, специфичными для брокера, такие как TTL, который сообщает неиспользуемой очереди, когда истечет срок ее действия по истечении определенного периода времени.
Прежде чем использовать очередь, ее необходимо объявить. Объявление очереди приведет к ее созданию, если она еще не существует.
Давайте проследим за жизненным циклом временной очереди сообщений.
1) Клиент создает очередь сообщений (Declare). Сервер подтверждает (Declare-Ok).
2) Клиент запускает потребителя очереди сообщений.
3) Клиент отменяет потребителя либо явно, либо закрыв канал и/или соединение.
4) Когда последний потребитель исчезает из очереди сообщений, сервер удаляет очередь сообщений.
Exchanges
Теоретически exchange является первой точкой входа сообщения, поступающего в брокер сообщений. Сообщения не публикуются непосредственно в очереди. Вместо этого producer отправляет сообщения на exchange, - его можно рассматривать как агента маршрутизации сообщений. Exchange отвечает за маршрутизацию сообщений в разные очереди с помощью атрибутов заголовка, привязок и ключей маршрутизации.
Exchanges, как и очереди, можно настроить с использованием таких параметров, как долговременный, временный и автоматическое удаление при создании. Устойчивые exchanges выдерживают перезапуск сервера и существуют до тех пор, пока не будут явно удалены. Временные exchanges существуют до тех пор, пока RabbitMQ не будет закрыт. Автоматически удаляемые exchanges удаляются, как только последний привязанный объект отсоединяется от exchange.
Давайте проследим за жизненным циклом exchange.
1) Клиент просит сервер убедиться, что exchange существует (Declare). Exchange создается, если он еще не существует.
2) Клиент публикует сообщения на exchange.
3) Клиент может удалить exchange (Delete).
В RabbitMQ существует четыре различных типа exchange, которые маршрутизируют сообщение по-разному, используя разные параметры и настройки привязок. Клиенты могут создавать свои собственные exchanges или использовать предопределенные exchanges по умолчанию, которые создаются при первом запуске сервера.
channel.exchange_declare(exchange='direct_exchange', exchange_type='direct')
Мы пока оставим различные типы exchange и вскоре поговорим о них подробнее.
Привязки (Bindings)
Привязка — это ассоциация или отношение между очередью и exchange. Она описывает, какая очередь заинтересована в сообщениях от данного exchange. Привязки могут принимать дополнительный параметр Route_key. Если вы помните, ключ маршрутизации также можно отправить вместе с сообщением. Ключ маршрутизации в привязке иногда называют ключом привязки, а ключ маршрутизации в сообщении — это то, на что обращает внимание exchange при доставке сообщений.
channel.queue_bind(exchange=exchange_name, queue=queue_name, routing_key='black')
Consumer Acknowledgements and Publisher Confirm
Сообщения в пути могут быть потеряны в случае сбоя соединения, и их необходимо будет передать повторно. Подтверждения позволяют серверу и клиентам знать, когда следует повторно передавать сообщения. Клиент может либо подтвердить сообщение при его получении, либо когда клиент полностью обработал сообщение. Подтверждение публикации — это та же концепция, но для публикации. Сервер подтверждает получение сообщения от издателя.
Сообщение можно считать успешно доставленным либо сразу же после его отправки, после его записи в сокет TCP, ИЛИ когда от клиента получено явное подтверждение. Подтверждение, отправленное вручную, может быть положительным или отрицательным.
После получения подтверждения сообщение может быть удалено из очереди. Если потребитель не может обработать сообщение, желаемым результатом может быть повторная постановка его в очередь и предоставление возможности другому потребителю получить и обработать его или повторная попытка обработки позже. Такие поставки могут быть отменены брокером или поставлены повторно в очередь. Такое поведение контролируется полем запроса. Если для поля установлено значение true, брокер запросит доставку. Запрошенное сообщение, если это возможно, помещается обратно в исходное положение в очереди и, следовательно, может быть немедленно готово к повторной доставке. Если все потребители запрашивают доставку, поскольку не могут обработать доставку, они создают цикл повторной доставки/запроса. Можно отслеживать количество повторных доставок и навсегда отклонять сообщения (отбрасывать их) или запланировать повторную доставку после задержки.
Виртуальные хосты (Virtual Hosts)
Виртуальные хосты (или vhosts) в RabbitMQ предоставляют способ разделения приложений, использующих один и тот же экземпляр RabbitMQ. Виртуальные хосты RabbitMQ создают логическую группу соединений, exchanges, очередей, привязок, разрешений пользователей и т. д. внутри экземпляра.
Думайте о виртуальных хостах как об отдельных контейнерах с уникальными именами. Внутри каждого контейнера vhost находится логическая группа exchanges, соединений, очередей, привязок, разрешений пользователей и других системных ресурсов.
Разные пользователи могут иметь разные разрешения для разных виртуальных хостов, а также можно создавать очереди и exchanges, которые существуют только на одном виртуальном хосте. Когда клиент устанавливает соединение с сервером RabbitMQ, он указывает виртуальный хост, в котором он будет работать.
Ресурсы, такие как exchanges и очереди, называются именованными ресурсами внутри контейнера vhost, что делает каждый vhost по существу мини-сервером RabbitMQ. При настройке RabbitMQ необходим хотя бы один виртуальный хост, который по умолчанию представляет собой косую черту «/».
Виртуальные хосты можно создавать через портал управления, через HTTP API или через Rabbitmqctl. Просмотрите виртуальные хосты, войдя во вкладку администратора и выбрав «Виртуальные хосты». Выберите опцию «Добавить новый виртуальный хост», чтобы создать новый виртуальный хост.
Разрешения внутри виртуального хоста и назначенные ему пользователи зависят от ваших системных требований, и вы сами можете назначать пользователей этому виртуальному хосту. Вновь созданный виртуальный хост всегда имеет набор exchanges по умолчанию, но не имеет других объектов и прав пользователя.
Виртуальные хосты не делят exchanges или очереди между собой, а пользователи, политики и т. д. уникальны для каждого виртуального хоста. По сути, виртуальные хосты RabbitMQ подобны виртуальной машине для физического сервера, позволяющей выполнять несколько безопасных операций приложений посредством виртуального, а не физического разделения. Поскольку разделение является виртуальным, важно помнить, что виртуальные хосты физически не отделены друг от друга и, следовательно, могут влиять на производительность друг друга.
Один и тот же брокер может использоваться в разных приложениях. Вы можете разделить среды, например производство на один виртуальный хост и промежуточное размещение на другой виртуальный хост в рамках одного и того же брокера вместо настройки нескольких брокеров.
Если в одной службе наблюдается всплеск трафика или ошибка кода, это может вызвать проблемы для других служб и повлиять на их производительность. Для каждой службы можно создать виртуальный хост для хранения всей логической инфраструктуры, что также позволяет лучше управлять индивидуальной топологией.