AMQP () — открытый протокол прикладного уровня для передачи сообщений между компонентами системы. Основная идея состоит в том, что отдельные подсистемы (или независимые приложения) могут обмениваться произвольным образом сообщениями через AMQP-брокер, который осуществляет маршрутизацию, возможно гарантирует доставку, распределение потоков данных, подписку на нужные типы сообщений.

Архитектуру протокола разработал John O’Hara из банка JP Morgan Chase & Co.

Протокол AMQP основан на трёх понятиях:

Сообщение (message) — единица передаваемых данных, основная его часть (содержание) никак не интерпретируется сервером, к сообщению могут быть присоединены структурированные заголовки. Точка обмена (exchange) — в неё отправляются сообщения. Точка обмена распределяет сообщения в одну или несколько очередей. При этом в точке обмена сообщения не хранятся. Точки обмена бывают трёх типов: fanout — сообщение передаётся во все прицепленные к ней очереди; direct — сообщение передаётся в очередь с именем, совпадающим с ключом маршрутизации (routing key) (ключ маршрутизации указывается при отправке сообщения); topic — нечто среднее между fanout и direct, сообщение передаётся в очереди, для которых совпадает маска на ключ маршрутизации, например, app.notification.sms.# — в очередь будут доставлены все сообщения, отправленные с ключами, начинающимися с app.notification.sms. Очередь (queue) — здесь хранятся сообщения до тех пор, пока не будут забраны клиентом. Клиент всегда забирает сообщения из одной или нескольких очередей.

Протокол можно разделить на два слоя:

Functional Layer — определяет набор команд которые выполняют работу от имени приложения. Transport Layer — обслуживает запросы приложения к серверу и сервера к приложению, управляет мультиплексированием каналов, фреймингом, кодировкой, heart-beating, представлением данныx, работой с ошибками.

Примеры очередей:

store-and-forward-queue — хранит и распространяет сообщения для многих потребителей (consumers) по принципу round robin. Постоянные, публичные private reply queue — хранит и распространяет сообщения для одного потребителя (consumer). Временные, приватные private subscription queue — хранит сообщения от многих источников и отправляет одному потребителю (consumer). Временные, приватные

Протокол не ограничивается этими тремя видами. Они указаны как пример реализации.

Терминология Exchange — сущность которая получает сообщения от приложений и при необходимости перенаправляет их в очереди сообщений. Binding: отношение между очередью сообщений и точками обмена. Routing key: виртуальный адрес, который точка обмена использует для принятия решения о дальнейшей маршрутизации.

Exchange Принимает сообщения от поставщика и направляет их в message queue в соответствии с предопределёнными критериями. Такие критерии называют bindings. Exchange — механизм согласования и маршрутизации сообщений. На основе сообщений и их параметров (bindings) принимают решение о перенаправлении в очередь или другой exchange. Не хранят сообщения.

Термин exchange означает алгоритм и экземпляр алгоритма. Также говорят exchange type и exchange instance.

AMQP определяет набор стандартных типов exchange. Приложения могут создавать свои exchange instance.

Каждый exchange реализует свой алгоритм маршрутизации. Существует несколько стандартных типов exchange, описанных в Functional Specification стандарта. Из них два являются важными:

Direct exchange — маршрутизирует на основе routing key. Базовый exchange — это direct exchange topic exchange — маршрутизирует на основе шаблона маршрутизации.

Сервер создаст несколько exchange, включая direct и topic. Они будут иметь wellknown имена и клиентские приложения смогут работать с ними.

Жизненный цикл Exchange Каждый AMQP-сервер предсоздаёт несколько экземпляров exchange. Эти экземпляры существуют когда сервер запущен и не могут быть уничтожены. AMQP-приложения могут также создавать свои собственные exchange. AMQP не использует для этого метод create, вместо этого экземпляр декларируется, который исходит из логики: «создать, если не создано, иначе продолжить». Можно сказать, что создание exchange идемпотентно. Вероятно приложения будут создавать exchange по мере необходимости, а затем уничтожать их за ненадобностью. AMQP предоставляет метод для уничтожения exchange.

Routing Key В общем случае exchange проверяет свойства сообщения, поля заголовка и содержимое его тела и, используя эти и, возможно, данные из других источников, решает, как направить сообщение. В большинстве простых случаев exchange рассматривает одно ключевое поле, которое мы называем Routing Key. Routing Key — это виртуальный адрес, который сервер exchange может использовать для принятия решения о направлении сообщения. Для маршрутизации типа point-to-point ключом маршрутизации обычно является имя очереди сообщений. Для маршрутизации pub-sub ключ маршрутизации обычно является значением иерархии топика (topic — смотри publication/subscruber). В более сложных случаях ключ маршрутизации может быть объединен с маршрутизацией по полям заголовка сообщения и/или его содержанием

Message Queue (очередь сообщений) Когда клиентское приложение создаёт очередь сообщений — оно может указать следующие свойства:

name — если не указано, сервер сам выбирает имя и отправляет его клиенту. Как правило, когда приложения совместно используют очередь сообщений они заранее договариваются об имени очереди сообщений, и когда приложение нуждается в очереди сообщений для своих собственных целей, оно позволяет серверу предоставлять имя. exclusive — если этот параметр установлен, то очередь существует пока существует текущее соединение. Очередь удаляется при разрыве подключения. durable — если установлен — очередь существует и активна при перезагрузке сервера. Очередь может потерять сообщения посланные во время перезагрузки сервера

Жизненный цикл сообщения Сообщение AMQP состоит из набора свойств и непубличного содержимого. Новое сообщение создается producer с использованием клиентского API AMQP. producer добавляет контент в сообщение и, возможно, устанавливает некоторые свойства сообщения. producer маркирует сообщение с помощью маршрутной информации, которая внешне похожа на адрес, но может быть любой. Затем producer отправляет сообщение в exchange. Когда сообщение поступает на сервер, exchange (обычно) направляет его в набор очередей, которые также существуют на сервере. Если сообщение немаршрутизируемо, exchange может удалить его или вернуть приложению. producer сам решает, как поступать с немаршрутизируемыми сообщениями.

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

Когда сообщение поступает в очередь сообщений, она немедленно пытается передать его потребителю через AMQP. Если это невозможно, то сообщение хранится в очереди сообщений (в памяти или на диске по просьбе producer) и ждет, пока consumer будет готов. Если отсутствует consumer, то очередь может вернуть сообщение producer через AMQP (опять же, если producer попросил об этом).

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

Сообщения producer и подтверждения consumer сгруппированы в транзакции. Когда приложение играет обе роли, что часто бывает, он выполняет смешанную работу: отправляет сообщения и отправляет подтверждения, а затем фиксация или откат транзакции.

Доставка сообщений от сервера к consumer не является транзакционной.

Producer Producer — клиентское приложение, которое публикует сообщения в exchange.

По аналогии с устройством электронной почты, можно заметить, что producer не отправляет сообщения непосредственно в очередь (message queue). Иное поведение нарушило бы абстракцию в модели AMQ. Это было бы похоже на жизненный цикл сообщения электронной почты: разрешение электронной почты, обход таблиц маршрутизации MTA и попадание непосредственно в почтовый ящик. Это сделало бы невозможной вставку промежуточной фильтрации и обработки, например, обнаружение спама.

Модель AMQ использует тот же принцип, что и система электронной почты: все сообщения отправляются в одну точку exchange или MTA, который проверяет сообщения на основе правил и информации, которая скрыта от отправителя, и направляет их к точкам распространения, которые также скрыты от отправителя. (and routes them to drop-off points that are also hidden from the sender — здесь точки распространения это drop-off points из документации).

Consumer Consumer — клиентское приложение, которое получает сообщения из очереди сообщений.

Наша аналогия с электронной почтой начинает разрушаться, когда мы смотрим на consumer (получателей). Почтовые клиенты пассивны — они могут читать почтовые ящики, но они не оказывают никакого влияния на то, как эти почтовые ящики заполняются. С помощью AMQP consumer также может быть пассивным, как и почтовые клиенты. То есть мы можем написать приложение, которое прослушивает определённую очередь сообщений и просто обрабатывает поступающую информацию. При этом очередь сообщений должна быть готова до старта приложения и должна быть «привязана» к нему.

Также consumer имеет следующие возможности:

создавать/удалять очереди сообщений определять способ заполнений очереди используя bindings выбирать разные exchanges, что может полностью изменить семантику маршрутизации

Это как обладать почтовой системой, которая на уровне протокола может:

создать новый почтовый ящик сказать MTA, что все сообщения с определённым заголовком должны быть скопированы в этот ящик полностью менять то, как именно почтовая система интерпретирует адреса и другие заголовки сообщения.

Автоматический режим Большинство интеграционных архитектур не нуждаются в таком уровне сложности. Большинство пользователей AMQP нуждаются в базовой функциональности из коробки. AMQP обеспечивает это следующим образом:

базовый (default) exchange для отправителей (producers) сообщений; базовый binding для очередей сообщений, который сортирует сообщения на основе совпадения routing key и имени очереди сообщений

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

Базовый binding не препятствует использованию очереди сообщений в более сложных конструкциях. Он позволяет использовать AMQP без конкретного понимания работы механизмов binding и exchange.

AMQP Command Architecture Секция описывает процесс взаимодействия приложения и сервера

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

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

Существует два различных метода диалога: