Це перша тема з якої варто починати огляд RabbitMQ, розуміння протоколів дозволяє сформувати грунт для подальшого вивчення. RabbitMQ підтримує такі протоколи: AMQP 0-9-1 і інші версії (0-9 / 0-8), AMQP 1.0 (Він кардинально відрізняється від інших AMQP протоколів), STOMP, MQTT, Streams, HTTP & WebSockets.
AMQP 0-9-1
AMQP (Advanced Message Queuing Protocol) - це основний протокол, який використовується в RabbitMQ.
Продюсер не відправляє дані в чергу напряму, замість цього він використовує окремий компонент, який називається exchange.
Компонент exchange прив’язаний до певного набору черг. Для ідентифікування кожної прив’язаності черги до exchange, яке називається binding, існує окрема стрічка, наприклад: “binding1“.
Для того, щоб exchange знав куди йому треба направити повідомлення він очікує від продюсер routing key (теж стрічка), який мапить до різних bindings.
Таким чином продюсер сам може визначити в яку саме чергу він хоче записати дані і передати дані конкретному консюмеру.
Якщо ви хочете зробити, щось схоже в Kafka, на рівні партицій, то треба змінити алгоритм читання консюмером топіка (RoundRobinAssignor), щоб він читав тільки одну партицію і записувати дані за одним ключем.
Є різні типи exchange компонента:
Direct Exchange - повідомлення відправляється до конкретної черги
Topic Exchange - повідомлення відправляється до групи черг
Fanout Exchange - повідомлення відправляється до всіх черг
Headers Exchange - замість routing key використовуються headers (структура ключ-значення, яка мапиться схожим чином і теж приходить від продюсера)
Також у RabbitMQ є дефолтний exchange, який працює як direct-exchange, щоб його використовувати, передавайте як назву exchange: ““. Він створюватиме і прив’язуватиме до себе черги за routing key, які до нього будуть приходити від продюсера.
Останній важливий компонент AMQP, це канали. AMQP побудовний на TCP (що робить протокол бінарним), будь-яке з’єднання брокера і клієнта відбувається через TCP протокол, а канал є сесією програми поверх цього TCP з’єднання (Канали знаходяться на application рівні моделі OSI).
Канал — це віртуальне з'єднання всередині з'єднання. Іншими словами, канал мультиплексує TCP-з'єднання. Як правило, кожен процес створює лише одне TCP-з’єднання та використовує кілька каналів у цьому з’єднанні для різних потоків.
В Java клієнті є обидва класи Connection(TCP) і Channel(AMQP), які оперують з’єднанням брокер-клієнт на двох різних рівнях. Channel використовується для відправлення прямих команд брокеру, ви можете використовувати скільки завгодно channel з’єднань у своїй програмі, не перевантажуючи брокера TCP-з’єднаннями.
AMQP 1.0
Є багато різних версій AMQP, але часто виділяють два стандарти: 0-9-1 та 1.0.
AMQP 1.0 є оновленою версією протоколу Advanced Message Queuing Protocol (AMQP), яка сильно відрізняється від минулої версії.
Є деякі мажорні відмінності між цими протоколами:
SASL (Simple Authentication and Security Layer) протокол, для забезпечення безпеки комунікації між брокером та клієнтом.
1.0 оперує концептом сесії, яка керує потоком комунікацх поверх з’єднання, адреси.
An AMQP session correlates two unidirectional channels to form a bidirectional, sequential conversation between two containers. Sessions provide a flow control scheme based on the number of transfer frames transmitted. Since frames have a maximum size for a given connection, this provides flow control based on the number of bytes transmitted and can be used to optimize performance. @Oasis AMQP Doc
Використовуються також адреси, вони дозволяють прямий запис в чергу.
An AMQP address determines where a message is sent to or consumed from. What internal object an AQMP address refers to and how an AMQP address is resolved is not defined by the AMQP specification because different AMQP brokers have different models to receive, store, and send messages. @RabbitMQ Doc
Також є деякі інші відмінності, які перелічені в таблиці.
Feature | AMQP 1.0 | AMQP 0.9.1 |
---|---|---|
Protocol | Binary protocol | Text protocol |
Models | Sender/Receiver, Publish/Subscribe, Request/Response | Exchange/Queue |
Queues | Stateful | Stateless |
Messages | Properties and Application Properties | No properties |
Transport | Pluggable | Fixed TCP |
Routing | Based on Address | Based on Route |
Linking | Dynamic | Static |
Sessions | Concept of Sessions | No Sessions |
Security | Authentication & Authorization | No Authentication |
Transaction | Supported | Not Supported |
Header | Optional | Mandatory |
Flow | Window-based | Credit-based |
State | Symmetric | Asymmetric |
Durable | Optional | Mandatory |
Timeout | Optional | Mandatory |
TTL | Optional | Mandatory |
Redeliver | Optional | Mandatory |
Dead-Letter | Optional | Mandatory |
Name | Optional | Mandatory |
Routing | Based on Address | Based on Route |
Exchanges | Multi-cast | Uni-cast |
Consumer | Control | No Control |
Delivery | Guarantee | No Guarantee |
Encoding | Pluggable | Fixed |
Офіційна документація по AMQP 1.0 (Oasis)
Джерело таблички (1.0 vs 0-9-1)
MQTT
MQTT (Message Queuing Telemetry Transport) - це легкий протокол для передачі повідомлень у мережевих з'єднаннях і він не використовує ні черг ні складної маршрутизації (exchange & binding & routing key), а просто транслює повідомлення від продюсера до консюмера через топік, що робить протокол популярним в IoT.
MQTT створений для комунікації віддалених пристроїв, які комунікують з низькою пропускною здатністю.
Топік - це ієрархічна адреса, до якої можна підписатися для отримання повідомлень. Наприклад, "office/home/lamp" може бути топіком для передавання інформації про взаємодію з лампою в офісі, або вдома.
Приклад топік підписки: Якщо консюмер підписаний на топік myhome/groundfloor/temperature то він отримає всі меседжі від продюсера які містять топік myhome/, але проігнорує myhome/secondfloor
Продюсери вказують топіки у які вони хочуть записати повідомлення, консюмери вказують топіки з яких хочуть читати. Кардинальна відмінність полягає в тому, що топіки не є структурою даних, це просто визначений зв’язок між продюсером і консюмером. Якщо продюсер запише повідомлення в топік, а консюмер не буде підписаний на цей топік, то повідомлення просто втратиться.
STOMP
STOMP (Simple Text Oriented Messaging Protoco) - це простий текстовий протокол, який описує те, як дані приходять до брокера.
STOMP не працює ні з топіками ні з чергами напряму. Продюсер використовує SEND семантику з стрічкою, яка описує пункт призначення (destination) для повідомлення. Коли повідомлення доходить до брокера, він мапить повідомлення з топіками, чергами, або ексчейнджами. Консюмери підписуються на ці пункти призначення і споживають повідомлення.
HTTP and WebSockets
Тут доволі просто, HTTP це реквест/респонс комунікація. А веб сокети - бомбардують брокер без необхідності отримувати відповіді.
Веб сокети зручно використовувати, якщо клієнт відправляє багато асинхронних повідомлень з браузера, а HTTP, якщо необхідна синхронна комунікація.
Ось тут гарний і детальний пост про те, як працюють веб сокети.
RabbitMQ Streams
Stream - це постійна реплікована структура даних, яка може виконувати ті самі завдання, що і черга.
Stream нагадує те, як дані зберігаються в Kafka, бо це теж log append only структура. Консюмери зчитують повідомлення скільки завгодно разів.
Streams треба використовувати коли:
1. Повідомлення треба доставити до великої кількості консюмерів
2. Треба програвати дані декілька разів
3. Важлива пропускна здатність. Log-based структури завжди швидші.
4. Треба зберігати великі об’єми даних
No persistent queue types are able to deliver throughput that can compete with any of the existing log based messaging systems. Streams have been designed with performance as a major goal. @RabbitMQ Doc
Грубо кажучи, RabbitMQ Streams робить меседж брокер менш схожим на MQ брокер і більш схожим на меншого брата Кафки.