Брокер сообщений ActiveMQ
ActiveMQ лучше всего описать, как классическую систему обмена сообщениями. Она была написана в 2004 году, восполняя потребность в брокере сообщений с открытым исходным кодом. В то время, если вы хотели использовать обмен сообщениями в своих приложениях, единственным выбором были дорогие коммерческие продукты.
ActiveMQ была разработана как реализация спецификации Java Message Service (JMS). Это решение было принято, чтобы удовлетворить требования к реализации JMS-совместимого обмена сообщениями в проекте Apache Geronimo — сервере приложений J2EE с открытым исходным кодом.
Система обмена сообщениями (или промежуточное ПО, ориентированное на сообщения, как ее иногда называют), реализующая спецификацию JMS, состоит из следующих компонентов:
1. Брокер Центральная часть промежуточного программного обеспечения, распределяющая сообщения.
2. Клиент Часть программного обеспечения, которая перебрасывает сообщения с помощью брокера. Она, в свою очередь, состоит из следующих артефактов:
- Код, использующий API JMS.
- JMS API — это набор интерфейсов для взаимодействия с брокером в соответствии с гарантиями, изложенными в спецификации JMS.
- Клиентская библиотека системы, которая обеспечивает реализацию API и взаимодействует с брокером.
Клиент и брокер общаются друг с другом через протокол прикладного уровня, также известный, как протокол взаимодействия. Спецификация JMS оставила детали этого протокола конкретным реализациям.
JMS использует термин провайдер для описания реализации вендором системы обмена сообщениями, лежащей в основе API JMS, которая включает брокер, а также ее клиентские библиотеки.
Выбор в пользу внедрения JMS имел далеко идущие последствия для имплементационных решений, принятых авторами ActiveMQ. В самой спецификации изложены четкие указания по обязанностям клиента системы обмена сообщениями и брокера, с которым он общается, отдавая предпочтение обязательству брокера распределять и доставлять сообщения. Основная обязанность клиента — взаимодействовать с адресатом (очередью или топиком) отправляемых им сообщений. Сама спецификация направлена на то, чтобы сделать взаимодействие API с брокером относительно простым.
Это направление, как мы увидим позже, сильно повлияло на производительность ActiveMQ. В дополнение к сложностям брокера, пакет совместимости для спецификации, предоставленной Sun Microsystems, имел множество нюансов, с их собственным влиянием на производительность. Данные нюансы должны были все быть учтены, чтобы ActiveMQ считалась совместимой с JMS.
Связь
Хотя API и ожидаемое поведение были хорошо определены в спецификации JMS, фактический протокол связи между клиентом и брокером был намеренно исключен из спецификации, чтобы существующие брокеры могли быть сделаны JMS-совместимыми. Таким образом, ActiveMQ был свободен в определении своего собственного протокола взаимодействия — OpenWire. OpenWire используется реализацией клиентской библиотеки ActiveMQ JMS, а также ее аналогами в .Net и C++: NMS и CMS, которые являются подпроектами ActiveMQ, размещенными в Apache Software Foundation.
Со временем в ActiveMQ была добавлена поддержка других протоколов взаимодействия, что увеличило возможности взаимодействия с другими языками и средами:
1. AMQP 1.0
Расширенный протокол очереди сообщений (Advanced Message Queuing Protocol) (ISO / IEC 19464:2014) не следует путать с его предшественником 0.X, который реализован в других системах обмена сообщениями, в частности в RabbitMQ, использующий 0.9.1. AMQP 1.0 является двоичным протоколом общего назначения для обмена сообщениями между двумя узлами. Он не имеет понятия клиентов или брокеров и включает в себя такие функции, как управление потоками, транзакции и различные QoS (Quality of service: не более одного раза, не менее одного раза и точно один раз).
2. STOMP
Простой / потоковый текстовый протокол обмена сообщениями (Simple/Streaming Text Oriented Messaging Protocol), простой в реализации протокол, который имеет десятки клиентских реализаций на разных языках.
3. XMPP
Расширяемый протокол обмена сообщениями и присутствия. (Extensible Messaging and Presence Protocol). Ранее называемый "Jabber", этот протокол, основанный на XML, был первоначально разработан для систем чатов, но был расширен за пределы его первоначальных сценариев использования для включения обмена сообщениями типа «публикация-подписка».
4. MQTT
Легковесный протокол «публикация-подписка» (ISO / IEC 20922:2016), используемый для приложений «Машина-Машина» (M2M) и «Интернет вещей» (IoT).
Учитывая это, сейчас, когда мы говорим об ActiveMQ, мы больше не ссылаемся исключительно на стек взаимодействия, основанный на библиотеках JMS / NMS / CMS и протоколе OpenWire. Становится все более популярным сочетание и подбор языков, платформ и внешних библиотек, которые лучше всего подходят для данного приложения. Например, возможно, чтобы приложение JavaScript выполнялось в браузере с использованием MQTT библиотеки Eclipse Paho для отправки сообщений в ActiveMQ через веб-сокеты и эти сообщения читались серверным процессом C++, который использует AMQP посредством библиотеки Apache Qpid Proton. С этой точки зрения ландшафт обмена сообщениями становится все более разнообразным.
Заглядывая в будущее, AMQP, в частности, будет иметь гораздо больше возможностей, чем сейчас, поскольку компоненты, которые не являются ни клиентами, ни брокерами, становятся более знакомой частью ландшафта системы обмена сообщениями. Например, Apache Qpid Dispatch Router выступает в роли маршрутизатора сообщений, к которому клиенты подключаются напрямую, позволяя различным адресатам обрабатывать разные адреса, а также предоставляя возможность шардинга (разделения).
При работе со сторонними библиотеками и внешними компонентами необходимо учитывать, что они имеют переменное качество и могут быть несовместимы с функциями, предоставляемыми в ActiveMQ. Как очень простой пример — невозможно отправить сообщения в очередь через MQTT (без настройки маршрутизации в брокере). Таким образом, вам нужно будет потратить некоторое время на работу с опциями, чтобы определить стек системы обмена сообщений, наиболее подходящий для требований вашего приложения.
Компромисс между производительностью и надежностью
Прежде чем мы углубимся в детали того, как работает обмен сообщениями «точка-точка» в ActiveMQ, нам нужно немного поговорить о том, с чем сталкиваются все системы с интенсивной обработкой данных: компромисс между производительностью и надежностью.
Любая система, принимающая данные, будь то брокер сообщений или база данных, должна быть проинструктирована о том, как следует обрабатывать эти данные в случае сбоев. Сбой может принимать различные формы, но для простоты мы сузим его до ситуации, когда система теряет питание и немедленно отключается. В такой ситуации нам нужно порассуждать о том, что случится с данными, которые были в системе. Если данные (в данном случае сообщения) находились в памяти или в энергозависимой части железа, например в кэше, то эти данные будут потеряны. Однако, если данные были отправлены в энергонезависимое хранилище, например на диск, они снова будут доступны, когда система вернется в работу.
С этой точки зрения имеет смысл, что, если мы не хотим потерять сообщения в случае сбоя брокера, нам нужно записать их в постоянное хранилище. Стоимость этого конкретного решения, к сожалению, довольно высока.
Учтите, что разница между записью мегабайта данных на диск в 100-1000 раз медленнее, чем запись в память. Таким образом, разработчик приложения должен принять решение относительно того, стоит ли надежность сообщения потери производительности. Решения, подобные этим, должны приниматься на основе сценария использования.
Компромисс между производительностью и надежностью основан на спектре вариантов. Чем выше надежность, тем ниже производительность. Если вы решите сделать систему менее надежной, например, сохраняя сообщения только в памяти, ваша производительность значительно возрастет. По умолчанию JMS настроен на то, что ActiveMQ из коробки обеспечивает надежность. Существует множество механизмов, которые позволяют настроить брокер и взаимодействие с ним на позицию в этом спектре, которая лучше всего подходит для конкретных сценариев использования системы обмена сообщений.
Этот компромисс применяется на уровне отдельных брокеров. Тем не менее, по завершении настройки отдельного брокера, возможно масштабировать систему обмена сообщениями за пределы этой точки путем тщательного исследования потоков сообщений и разделения трафика между несколькими брокерами. Этого можно достичь, предоставив определенным адресатам их собственные брокеры или разделив общий поток сообщений либо на уровне приложения, либо с помощью промежуточного компонента.