1. Зачем нужны messageMQ?

Message Queue - это асинхронное взаимодействие между компонентами в распределенной системе.

Очередь сообщений – это форма асинхронной коммуникации между сервисами, применяемая в бессерверных и микросервисных архитектурах. Сообщения хранятся в очереди, пока не будут обработаны и удалены. Использование очередей сообщений решает сразу две задачи:

  • Сокращает время ожидания пользователя за счет асинхронной обработки

  • Предотвращает потерю информации при сбоях

В свою очередь сообщение - это просто передача какого-то набора данных и этот набор данных передается на какой-то удаленный сервер. Это чем-то похоже HTTP Request с данными (текст, json и т.п.), который передается на удаленный сервер.

2. Преимущества MQ

2.1. Повышенная производительность

Компоненты (producer и consumer) взаимодействую с очередью (middleware), не друг с другом. Producer добавляет сообщения в очередь и не дожидается их обработки. И consumers обрабатывают сообщения, когда они доступны. Ни один компонент не пребывает в ожидании другого - это оптимизирует поток данных. Тем самым, повышается производительность независимых компонент.

2.2. Масштабируемость(горизонтальная)

И producer, и consumer, и message broker могут легко масштабироваться. В случае увеличения нагрузки на компонент, можно распределить её между экземплярами.

2.3. Отказоустойчивость

Если consumer, который обрабатывает сообщения из очереди падает, то сообщения могут быть добавлены в очередь на обработку позднее, когда система восстановится.

Недостатки очередей сообщений

  1. По сути, это еще одна система, которую необходимо купить/установить, правильно сконфигурировать и поддерживать. Также потребуются дополнительные мощности.

  2. Если брокер когда-либо выйдет из строя, это может остановить работу многих систем, взаимодействующих с ним. Как минимум необходимо позаботиться о резервном копировании данных.

  3. С ростом числа очередей усложняется и отладка. При синхронной обработке сразу очевидно, какой запрос вызвал сбой, например, благодаря иерархии вызовов в IDE. В очередях потребуется позаботиться о системе трассировки, чтобы быстро связать несколько этапов обработки одного запроса для обнаружения причины ошибки.

3. Обобщенная схема взаимодействия компонентов MQ

message broker example scema

Producer отправляет сообщение в некоторую именованную очередь. Не ожидает подтверждения доставки. Сообщение хранится в очереди, пока consumer не вытянет его для обработки (зависит от модели поведения consumer по отношению к очереди).

Message broker - центральная часть промежуточного программного обеспечения (middleware), распределяющая сообщения. Так как очереди могут использоваться несколькими производителями и потребителями одновременно, обычно их реализуют с помощью дополнительной системы, называемой broker. Брокер сообщений (Message Broker) занимается сбором и маршрутизацией сообщений на основе предопределенной логики. Сообщения могут передаваться с некоторым ключом — по этому ключу брокер понимает, в какую из очередей (одну или несколько) должно попасть сообщение.

Брокеры сообщений – это модули ПО, благодаря которым приложения, службы и системы могут взаимодействовать и обмениваться информацией. Брокеры сообщений преобразуют сообщения от разных формальных протоколов обмена сообщениями, позволяя взаимозависимым службам напрямую «общаться» друг с другом, даже если они написаны на разных языках или работают на других платформах. Брокеры сообщений валидируют, маршрутизируют, хранят и доставляют сообщения назначенным получателям. Брокеры действуют как посредники между приложениями, позволяя продюсерам отправлять сообщения, не зная о количестве, активности и местонахождении консьюмеров.

Message brokers: Apache Kafka, RabbitMQ, Apache ActiveMQ, WSO2, Memphis

4. В каком режиме работает передача информации(модели доставки сообщений для consumers)?

MQ поддерживают получение сообщений как методом Push, так и методом Pull:

  1. Метод Pull подразумевает периодический опрос очереди consumer по поводу наличия новых сообщений; pull-модель — consumers сами отправляют запрос раз в n секунд к message broker для получения новой порции сообщений. Эффективна только при возможности группировать сообщения в батчи, таким образом достигая лучшей пропускной способности. К минусам модели можно отнести потенциальную разбалансированность нагрузки между разными consumers, а также более высокую задержку обработки данных. В Kafka именно consumers определяют, когда прочитать сообщение (т.е. Kafka использует pull модель).

  2. Метод Push — message broker отправляет сообщение customer. Это дизайн паттерн «Издатель/Подписчик» (Publisher/Subscriber). push-модель — Producer(Publisher) отправляет сообщение в message broker. Message broker отправляет сообщение из очереди соответствующему customer(subscriber). По такой модели, например, работает RabbitMQ. Она снижает задержку обработки сообщений и позволяет эффективно балансировать распределение сообщений по consumers.

5. RabbitMQ

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

AMQP(Advanced Message Queuing Protocol) - протокол прикладного уровня для передачи сообщений между компонентами системы.

RabbitMQ написан на Erlang (функциональный язык с динамической типизацией). Имеется реализация клиентов для доступа к RabbitMQ для целого ряда языков программирования, в том числе для Perl, Python, Ruby, PHP. Поддерживается горизонтальное масштабирование для построения кластерных решений.

В RabbitMQ применяется push модель: это помогает предотвратить перегрузку пользователей через ограничение предварительной выборки, настроенное consumers. Идеальный подход для обмена сообщениями с малой задержкой, который отлично работает с архитектурой RabbitMQ на основе очередей. Этот инструмент можно представить как почтовое отделение, которое получает, хранит и отправляет почту; только RabbitMQ принимает, хранит и передает сообщения с двоичными данными.

Кратко работу RabbitMQ можно описать следующим образом:

  • Producer(Publisher) отправляет сообщение в message broker.

  • Там оно попадает в компонент Exchange. Это пункт роутинга сообщений, в нем определяется в какую очередь будет отправлено дальше сообщение.

  • Exchange маршрутизирует сообщение в одну или несколько очередей(либо в другие exchanges) в соответствии с правилами привязки (binding) между ним и очередью.

  • Consumers поддерживают постоянные TCP-соединения с RabbitMQ и объявляют, какую очередь они получают.

  • RabbitMQ проталкивает (push) сообщения получателям.

  • Если включен механизм подтверждения (acknowledgement mode / manual), consumer отправляет подтверждение успеха или ошибки получения сообщения. После успешного получения, сообщение удаляется из очереди. Если механизм подтверждения не включен (automatic acknowledgement mode), брокер проталкивает сообщение подписчику и удаляет его из очереди(сообщение считается успешно доставленным).

rabbit scema

6. Publisher(Producer)

(добавить описание)

7. Message

(добавить описание)

8. Exchange

При обмене сообщениями между поставщиками и подписчиками, сообщения не отправляются непосредственно в очереди. Сначала они проходят через Exchange, который перенаправляет их в очереди назначения.

Exchange - это компонент, который принимает сообщение от producer и направляет его дальше либо в одну очередь, либо в несколько очередей, либо в другие exchanges с помощью headers arguments, привязок (bindings) и ключей маршрутизации (routing key).

Binding — это «ссылка», которая настраивается для привязки очереди к exchange.

Routing key — это атрибут сообщения, на который обращает внимание exchange при принятии решения о том, как направить сообщение в очереди (в зависимости от exchange type).

Exchange можно настроить с такими параметрами, как name, exchange type, durability, auto-delete, arguments.

  • name (имя exchange)

  • type (тип маршрутизации)

  • durability (true - после перезагрузки сервера, exchange не удаляется)

  • auto-delete (автоматически удаляется exchange, если нет ни одной привязанной очереди)

  • arguments (optional, используется плагинами и специфичными для брокера функциями)

8.1. Exchange types

  • direct exchange;

  • fanout exchange;

  • topic exchange;

  • headers exchange;

  • dead letter exchange (AMQP extension);

Direct exchange

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

Сообщение помещается в очередь (очереди) с ключом привязки, точно совпадающим с ключом маршрутизации сообщения.

direct exchange

Fanout exchange

Предоставленные ключи маршрутизации игнорируются. Сообщения будут отправлены во все связанные с exchange очереди. Самый быстрый тип распределения.

Fanout exchange может быть полезен, когда одно и то же сообщение необходимо отправить в одну или несколько очередей с потребителями, которые могут обрабатывать одно и то же сообщение по-разному.

fanout exchange

Topic exchange

Сообщение будет направлено в одну или несколько очередей на основе соответствия между ключом маршрутизации сообщений и шаблоном, который использовался для привязки очереди к exchange. Topic type часто используется для реализации различных вариантов шаблона publisher/subscriber.

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

topic exchange

Headers exchange

Предназначен для маршрутизации по нескольким атрибутам, которые легче выразить в виде заголовков сообщений (message headers), чем в ключе маршрутизации. Сообщение соответствует, если значение заголовка равно значению, указанному в binding.

При связывании очереди к headers exchange можно указать более одного заголовка. Можно привязать очередь к обмену заголовками, используя более одного заголовка для сопоставления. Аргумент привязки «x-match» показывает должно ли быть полное совпадение или частичное. Когда для аргумента «x-match» задано значение «any», достаточно только одного совпадающего значения заголовка. В качестве альтернативы установка «x-match» на «all» означает, что все значения должны совпадать.

headers exchange

Dead letter exchange

Могут возникнуть ситуации, когда сообщение попавшее в message broker может остаться необработанным.

  • истекает TTL (истекает время жизни для сообщения)

  • размер очереди достигает предела

  • consumer возвращает негативный ответ на обработку (negatively acknowledged)

Сообщение перенаправляется в альтернативный exchange(DLX), а уже от туда в привязанную к нему очередь.

Настраивается либо с помощью policy, либо с помощью queue arguments. Если механизм не настроен, по умолчанию сообщение удаляется.

Смотри подробнее: https://www.rabbitmq.com/dlx.html

9. Queue

Queue - это структура данных на диске или в оперативной памяти, которая хранит ссылки на сообщения и отдает их копии consumers (потребителям).

Очереди в RabbitMQ — это FIFO ("first in, first out").

У очередей есть свойства, определяющие их поведение:

  • name

  • durability (очередь сохраняет свое состояние в случае перезапуска broker)

  • exclusive (очередь доступна только тем, кто получил доступ в рамках одного connection)

  • auto-delete (очередь автоматически удаляется, если нет активных подключений. Нет подключенных consumers)

  • arguments (optional, используется плагинами и специфичными для брокера функциями)

9.1. Durability

Очереди могут быть устойчивыми или временными (durability - true/false). Метаданные долговременной очереди хранятся в неком storage, а метаданные временной очереди по возможности хранятся в памяти.

Временные очереди не переживут перезапуск узла. Сообщения во временных очередях также будут удалены.

Устойчивые очереди будут восстановлены при загрузке узла, включая сообщения находящиеся в них(зависит от настройки durability самого сообщения).

9.2. Arguments

  • x-message-ttl(x-message-time-to-live) — позволяет установить время истечения срока жизни сообщения в миллисекундах. Если создание очереди происходит с установленным значением аргумента x-message-ttl, то такая очередь будет автоматически исключать сообщения, у которых истек срок действия. Установка значения аргумента x-message-ttl задает максимальный возраст для всех сообщений в данной очереди. Создание такой очереди позволяет предотвратить получение устаревшей информации. Это можно использовать в системах реального времени. Если у очереди для которой задан обменник для отклоненных сообщений установить значение аргумента x-message-ttl, то отклоненные сообщения в данной очереди начнут обладать сроком жизни.

  • x-max-length — задает максимальное число сообщений в очереди. Если число сообщений в очереди начинает превышать максимальное число, то начинают удаляться самые старые.

  • x-overflow — данный аргумент используется для настройки поведения в результате переполнения очереди. Доступны два значения: drop-head (значение по умолчанию) и reject-publish. Если выбрать drop-head, то самые старые сообщения будут удаляться. Если выбрать reject-publish, то прием сообщений будет приостановлен.

  • x-dead-letter-exchange — задает exchange, в который направляются недоставленные сообщения, которые не поставлены повторно в очередь.

  • x-dead-letter-routing-key — задает не обязательный ключ маршрутизации для отвергнутых сообщений.

  • и др.

10. Binding

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

Если сообщение не может быть перенаправлено ни в одну очередь (например, из-за отсутствия binding), оно либо удаляется, либо возвращается издателю(зависит от установленных механизмов).

11. Subscriber(Consumer)

(добавить описание)

12. Подробнее о разнице между Apache Kafka и RabbitMQ

12.1. Поток данных.

RabbitMQ использует определенный ограниченный поток данных. Продюсер создает и отправляет сообщения, а консьюмер их принимает. Apache Kafka использует неограниченный поток данных, при этом пары «ключ-значение» непрерывно передаются в назначенную тему.

12.2. Использование данных.

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

12.3. Обмен сообщениями.

RabbitMQ отправляет пользователям сообщения, которые удаляются из очереди после их обработки и подтверждения. Кафка – это журнал. Он использует непрерывные цепочки сообщений, которые сохраняются в очереди до истечения срока хранения. В отличие от большинства систем, очередь сообщений в Kafka является постоянной. Отправленные данные хранятся до тех пор, пока не истечет указанные период. Сообщения не удаляются после получения, их можно перечитывать. В RabbitMQ сообщение хранится до тех пор, пока принимающее приложение не получит его из очереди. Как только подписчик отмечает, что сообщение получено, оно удаляется.

12.4. Протокол

RabbitMQ поддерживает несколько стандартизированных протоколов: AMQP, MQTT, STOMP и др. Это позволяет заменить его на любой брокер на основе AMQP. Kafka использует пользовательский протокол поверх TCP/IP для связи между приложениями и кластером. Вы не сможете так просто удалить или заменить эту платформу, потому что она единственная реализует данный протокол.

12.5. Масштабирование

Kafka подходит для горизонтального масштабирования путём добавления большего количества машин. RabbitMQ в основном предназначается для вертикального масштабирования путём увеличения мощности.

12.6. Модель проектирования

RabbitMQ использует модель умный брокер/тупой консьюмер. Брокер последовательно доставляет сообщения консьюмерам и отслеживает их статус. Apache Kafka использует модель тупого брокера/умного консьюмера. Этот инструмент не отслеживает сообщения, которые прочитал каждый пользователь. Кафка запоминает только непрочитанные сообщения, сохраняя их в течение установленного периода времени. Консьюмеры должны самостоятельно следить за своей позицией в каждом журнале.

12.7. Топология

RabbitMQ использует топологию обмена очереди: сообщения отправляются на обмен, откуда затем рассылаются в различные привязки очередей для использования консьюмерами. Кафка использует топологию Publish/Subscribe, отправляя сообщения через поток в соответствующие топики, которые затем потребляются пользователями в разных авторизованных группах.

13. _Ресурсы: