Что такое брокеры сообщений?

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

Чего ждать? Это было немного сложно, позвольте мне упростить. Брокеры сообщений действуют как посредники между различными микросервисами (частями) вашего приложения. Эти посредники помогают различным частям вашего приложения легко и эффективно взаимодействовать друг с другом. Например, скажем, ваше приложение представляет собой веб-сайт электронной коммерции. Микросервис, который обрабатывает размещение заказов, может захотеть взаимодействовать (отправлять запросы на информацию) с микросервисом, который поддерживает инвентаризацию того, какие продукты и сколько продуктов доступны для продажи. На крупных веб-сайтах электронной коммерции миллионы пользователей покупают сотни миллионов товаров. Подумайте о безумно большом количестве запросов, которые первый описанный микросервис должен будет отправить второму микросервису. Здесь в игру вступают брокеры сообщений, они делают эти задачи очень простыми и эффективными.

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

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

Зачем нам нужны брокеры сообщений?

Но зачем нам брокеры сообщений? Разве старых хороших RESTful HTTP API не должно хватить для облегчения взаимодействия между различными приложениями / микросервисами?

Ну, для начала, что, если вызванный микросервис по какой-то причине вышел из строя и не может ответить? Это может привести к потере HTTP-запросов, что, в свою очередь, приведет к потере информации. Кроме того, поскольку HTTP-запросы по своей природе являются блокирующими, клиент, вызвавший сбой микросервиса, будет продолжать опрашивать данные в течение долгого времени, прежде чем, в конечном итоге, продолжит работу. Создание асинхронных HTTP API может оказаться трудоемкой задачей.

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

Брокеры сообщений широко используются, когда гарантированная доставка сообщений имеет первостепенное значение. Работа почтового отделения - известный пример, используемый для объяснения этой концепции. После того, как вы (производитель) отправите письмо, сбросив его в почтовый ящик (брокер сообщений) или отправив его в почтовое отделение, вы освобождаетесь от ответственности за письмо и можете быть уверены, что письмо будет получено. потребителем. В этом случае ответственность за гарантированную доставку письма ложится на почтовый отдел.

Еще один момент для обсуждения, в котором брокеры сообщений выделяются по сравнению с API HTTP, заключается в том, что этих брокеров можно легко масштабировать для надежной обработки миллионов и миллиардов запросов! Во время продаж на сайтах электронной коммерции несколько покупателей соперничают за ограниченное количество товаров и могут размещать свои заказы почти одновременно. Все эти заказы (сообщения / запросы) помещаются в очередь брокера сообщений и обрабатываются асинхронно.

Начало работы с RabbitMQ

В двух предыдущих разделах говорилось о том, что такое брокеры сообщений и каковы преимущества их использования по сравнению с более традиционными методами. RabbitMQ - это брокер сообщений с открытым исходным кодом, который широко используется такими компаниями, как Reddit, Instagram, NY Times, Google и т. Д. Сегодня мы попытаемся настроить базовый сервер RabbitMQ с использованием NodeJS, чтобы продемонстрировать, как он работает.

Первым шагом будет установка RabbitMQ в вашей системе. Вы можете сделать это, выполнив действия, указанные здесь, или используя образ Docker RabbitMQ, открыв свой терминал и выполнив следующую команду:

docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management

Это установит и запустит RabbitMQ на localhost на порту 5672.

Наша демонстрация потребует создания всего двух файлов - consumer.js и продюсера.js.

Давайте создадим папку и назовем ее rabbitMQ-starter. Мы будем использовать amqp.node, чтобы обеспечить связь между нашим производителем и потребителем. RabbitMQ использует для этого различные протоколы, и AMQP (Advanced Message Queuing Protocol) является одним из таких примеров. Установите клиент amqp.node, выполнив в терминале следующую команду:

npm install amqplib

Затем мы создаем наш файл Producer.js в папке rabbitMQ-starter:

После запроса библиотеки AMQP в строке 1 мы устанавливаем TCP-соединение с сервером RabbitMQ в строке 3. Затем мы создаем канал в строке 7. Думайте о канале как о соединении AMQP в TCP-соединении. Мы объявляем нашу очередь и сообщение в строках 11 и 12 соответственно. Затем мы проверяем, существует ли очередь в строке 14. Свойство долговечности в строке 15 пока можно игнорировать. Строка 17 говорит сама за себя, мы просто отправляем сообщение в очередь. Затем мы закрываем соединение, и производитель уходит.

После этого мы создаем наш файл consumer.js:

Начнем с требования библиотеки, создания соединения и канала, как в файле Producer.js. Затем мы объявляем очередь и даем ей то же имя, которое мы дали очереди в программе-производителе. После подтверждения того, существует ли очередь, мы потребляем сообщение из очереди в строке 17. В реальной жизни потребитель получает сообщения из очереди, а затем некоторое время тратится на обработку сообщений. Все это делается асинхронно. Чтобы продемонстрировать это, мы ввели в программу-получатель setTimeout, чтобы после получения каждого сообщения вводилась задержка в 3 секунды. Окончание обработки сообщения отмечается печатью «Готово» на консоли через 3 секунды.

Попробуем сейчас в терминале. Убедившись, что ваш сервер RabbitMQ запущен, запустите потребительскую программу, набрав в терминале следующее:

node consumer.js

Потребитель будет ждать поступления сообщения в очередь. Теперь запустите производителя, набрав в терминале следующее:

node producer.js

Производитель отправляет наше сообщение «Hello world» в очередь, и это сообщение получает потребитель. Через 3 секунды потребитель печатает «Готово», тем самым отмечая окончание обработки сообщения, и продолжает прослушивать любые дальнейшие сообщения.

Теперь, что, если после получения сообщения в потребителе мы выходим из программы-потребителя до того, как напечатать «Готово», то есть перед обработкой сообщения. Это будет имитировать сбой потребительского сервиса. Мы ожидаем, что сообщение будет получено и обработано потребителем, как только оно вернется в сеть, верно? Давай попробуем. Начиная с того места, где мы остановились раньше, потребитель все еще ожидает новых сообщений, отправляемых в очередь. Мы снова запускаем программу производителя и, конечно же, сообщение получено потребителем. Но прежде чем он сможет напечатать «Готово», мы выходим из потребительской программы. Затем мы снова запускаем программу-получатель и надеемся, что сообщение будет получено потребителем из очереди:

Однако этого не происходит. Потребителю не удается повторно получить сообщение из очереди, и, следовательно, информация теряется навсегда. Но разве RabbitMQ не должен был сохранять сообщения и гарантировать отсутствие потери информации? Что ж, RabbitMQ, в отличие от некоторых других брокеров сообщений, не сохраняет информацию, если это специально не указано! В строке 23 нашего файла consumer.js вы можете видеть, что для свойства noAck установлено значение «true». Следовательно, потребитель не отправляет серверу никаких подтверждений о том, было ли сообщение получено и было ли оно обработано или нет. Если мы установим для этого свойства значение «false», потребитель начнет отправлять подтверждения на сервер, и информация начнет сохраняться. Таким образом, если какое-либо необработанное сообщение обнаружено из-за того, что не было получено надлежащее подтверждение, оно будет снова отправлено потребителю, как только оно вернется в сеть. Давайте снова попробуем наш небольшой эксперимент - запустим программу-получатель, запустим программу-производитель, программа-получатель получит сообщение, закройте программу-получатель перед выводом «Готово», перезапустите программу-получатель, и мы увидим, что сообщение получено снова потребитель, таким образом гарантируя, что никакая информация не будет потеряна:

Может быть несколько потребителей и производителей. В случае сбоя потребителя сообщения, которые он использовал, автоматически отправляются другому потребителю. Давайте попробуем это, запустим один экземпляр производителя и два экземпляра потребителей. Производитель отправит сообщение, и оно будет получено первым потребителем. Закройте этого первого потребителя, и вы увидите, что сообщение автоматически получает второй потребитель!

И, наконец, что, если производитель отправляет большое количество сообщений? Чаще всего это случается в реальной жизни: продюсеры не отправляют только одно сообщение за раз. Мы можем увеличить количество потребителей, чтобы снизить нагрузку на любого отдельного потребителя. Давайте модифицируем нашу программу, чтобы отправлять по сто сообщений за раз:

Теперь у нас одновременно работают три потребителя и один производитель:

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

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

Вы можете найти оба файла для этого стартового проекта здесь:



Не стесняйтесь обращаться ко мне, если у вас возникнут какие-либо сомнения или предложения.

Ссылки: