Rabbitmq routing key что это
Rabbitmq routing key что это
This tutorial assumes RabbitMQ is installed and running on localhost on the standard port ( 5672 ). In case you use a different host, port or credentials, connections settings would require adjusting.
Where to get help
If you’re having trouble going through this tutorial you can contact us through the mailing list or RabbitMQ community Slack.
Prerequisites
As with other Python tutorials, we will use the Pika RabbitMQ client version 1.0.0.
What This Tutorial Focuses On
In the previous tutorial we built a simple logging system. We were able to broadcast log messages to many receivers.
Bindings
In previous examples we were already creating bindings. You may recall code like:
A binding is a relationship between an exchange and a queue. This can be simply read as: the queue is interested in messages from this exchange.
The meaning of a binding key depends on the exchange type. The fanout exchanges, which we used previously, simply ignored its value.
Direct exchange
Our logging system from the previous tutorial broadcasts all messages to all consumers. We want to extend that to allow filtering messages based on their severity. For example we may want the script which is writing log messages to the disk to only receive critical errors, and not waste disk space on warning or info log messages.
To illustrate that, consider the following setup:
Multiple bindings
Emitting logs
Like always we need to create an exchange first:
And we’re ready to send a message:
To simplify things we will assume that ‘severity’ can be one of ‘info’, ‘warning’, ‘error’.
Subscribing
Putting it all together
If you want to save only ‘warning’ and ‘error’ (and not ‘info’) log messages to a file, just open a console and type:
If you’d like to see all the log messages on your screen, open a new terminal and do:
And, for example, to emit an error log message just type:
Move on to tutorial 5 to find out how to listen for messages based on a pattern.
Production [Non-]Suitability Disclaimer
Please keep in mind that this and other tutorials are, well, tutorials. They demonstrate one new concept at a time and may intentionally oversimplify some things and leave out others. For example topics such as connection management, error handling, connection recovery, concurrency and metric collection are largely omitted for the sake of brevity. Such simplified code should not be considered production ready.
Please take a look at the rest of the documentation before going live with your app. We particularly recommend the following guides: Publisher Confirms and Consumer Acknowledgements, Production Checklist and Monitoring.
Getting Help and Providing Feedback
If you have questions about the contents of this tutorial or any other topic related to RabbitMQ, don’t hesitate to ask them on the RabbitMQ mailing list.
Help Us Improve the Docs 1 «Hello World!»
The simplest thing that does something
2 Work queues
Distributing tasks among workers (the competing consumers pattern)
3 Publish/Subscribe
Sending messages to many consumers at once
4 Routing
Receiving messages selectively
5 Topics
Receiving messages based on a pattern (topics)
6 RPC
7 Publisher Confirms
Reliable publishing with publisher confirms
RabbitMQ tutorial 3 — Публикация/Подписка
Хочу продолжить серию перевода уроков с официального сайта. Примеры будут на php, но их можно реализовать на большинстве популярных ЯП.
Публикация/Подписка
В предыдущей статье было рассмотрено создание рабочей очереди сообщений. Было сделано допущение, что каждое сообщение будет направлено одному обработчику(worker). В этой статье усложним задачу – отправим сообщение нескольким подписчикам. Этот паттерн известен как «publish/subscribe» (публикация/подписка).
Чтобы понять этот шаблон, создадим простую систему логирования. Она будет состоять из двух программ – первая будет создавать логи, вторая считывать и печатать их.
В нашей систему логирования каждая программа подписчик будет получать каждое сообщение. Благодаря этому, мы сможем запустить одного подписчика на сохранение логов на диск, а потом в любое время сможем создать другого подписчика для отображения логов на экран.
По существу, каждое сообщение будет транслироваться каждому подписчику.
Точки обмена(exchanges)
В предыдущих статьях для отправки и принятия сообщений мы работали с очередью. Теперь рассмотрим расширенную модель отправки сообщений Rabbit.
Основная идея в модели отправки сообщений Rabbit – Поставщик(producer) никогда не отправляет сообщения напрямую в очередь. Фактически, довольно часто поставщик не знает, дошло ли его сообщение до конкретной очереди.
Вместо этого поставщик отправляет сообщение в точку доступа. В точке доступа нет ничего сложного. Точка доступа выполняет две функции:
— получает сообщения от поставщика;
— отправляет эти сообщения в очередь.
Точка доступа точно знает, что делать с поступившими сообщениями. Отправить сообщение в конкретную очередь, либо в несколько очередей, либо не отправлять никому и удалить его. Эти правила описываются в типе точки доступа (exchange type).
Существуют несколько типов: direct, topic, headers и fanout. Мы остановимся на последнем типе fanout. Создадим точку с доступа с этим типом и назовем её – logs:
Тип fanout – очень прост. Он копирует все сообщения которые поступают к нему во все очереди, которые ему доступны. Это то что нам нужно для нашей системы логирования.
Просмотр списка точек доступа:
Чтобы посмотреть все точки доступа на сервере, необходимо выполнить команду rabbitmqctl:
Мы видим список точек доступа с наименованием amq.* и точку доступа без имени, которая используется по умолчанию (она не подходит для выполнения нашей задачи).
Наименование точек доступа.
В предыдущих статьях мы ничего не знали о точках доступа, но всё-таки могли отправлять письма в очередь. Это было возможно, потому что использовали точку доступа по умолчанию, которая идентифицируется пустой строкой “”.
Вспомним как раньше мы отправляли письма:
Здесь используется точка доступа по умолчанию или безымянная точка доступа: сообщение направляется в очередь, идентифицированную через ключ “routing_key”. Ключ “routing_key” передается через третий параметр функции basic_publish.
Теперь мы можем отправить сообщение в нашу именованную точку доступа:
Временные очереди:
Всё это время мы использовали наименование очередей (“hello“ или “task_queue”). Возможность давать наименования помогает указать обработчикам (workers) определенную очередь, а также делить очередь между продюсерами и подписчиками.
Но наша система логирования требует, чтобы в очередь поступали все сообщения, а не только часть. Также мы хотим, чтобы сообщения были актуальными, а не старыми. Для этого нам понадобиться 2 вещи:
— Каждый раз когда мы соединяемся с Rabbit, мы создаем новую очередь, или даем создать серверу случайное наименование;
— Каждый раз когда подписчик отключается от Rabbit, мы удаляем очередь.
В php-amqplib клиенте, когда мы обращаемся к очереди без наименовании, мы создаем временную очередь и автоматически сгенерированным наименованием:
Метод вернет автоматически сгенерированное имя очереди. Она может быть такой – ‘amq.gen-JzTY20BRgKO-HjmUJj0wLg.’.
Когда заявленное соединение оборвется, очередь автоматически удалиться.
Переплеты(Bindings)
Итак, у нас есть точка доступа с типом fanout и очередь. Сейчас нам нужно сказать точке доступа, чтобы она отправила сообщение в очередь. Отношение между точкой доступа и очередью называется bindings.
С этого момента, сообщения для нашей очереди проходят через точку доступа.
Посмотреть список binding-ов можно используя команду rabbitmqctl list_bindings.
Отправка во все очереди:
Программа продюсер, которая создает сообщения, не изменилась с предыдущей статьи. Единственное важное отличие – теперь мы направляем сообщения в нашу именованную точку доступа ‘logs’, вместо точки доступа по умолчанию. Нам нужно было указать имя очереди при отправки сообщения. Но для точки доступа с типом fanout в этом нет необходимости.
Рассмотрим код скрипта emit_log.php:
Как вы видите, после установки соединения мы создаем точку доступа. Этот шаг необходим, так как использование несуществующей точки доступа – запрещено.
Сообщение в точке доступа будут потеряны, так как ни одна очередь не связана с точкой доступа. Но это хорошо для нас: пока нет ни одного подписчика нашей точки доступа, все сообщения могут безопасно удалятся.
Код подписчика receive_logs.php:
Если вы хотите сохранить логи в файл, вам потребуется открыть консоль и набрать:
$ php receive_logs.php > logs_from_rabbit.log
Если вы хотите отобразить логи на экран, откройте еще одно окно и наберите:
$ php receive_logs.php
Ну и, конечно, запуск продюсера сообщений:
С помощью команды rabbitmqctl list_bindings мы можем удостовериться, что код правильно создал очередь и связал её с точкой доступа. С двумя открытыми программами receive_logs.php у вас должно получиться следующее:
В следующей статье будет описано, как прослушать только часть сообщений.
RabbitMQ. Часть 2. Разбираемся с Exchanges
Exchange — обменник или точка обмена. В него отправляются сообщения. Exchange распределяет сообщение в одну или несколько очередей. Он маршрутизирует сообщения в очередь на основе созданных связей ( bindings ) между ним и очередью.
Exchange не является Erlang-процессом. Из соображений масштабируемости exchange — это строка (ссылка на модуль с кодом, где лежит логика маршрутизации) во встроенной базе данных mnesia. 1 тысяч обменников будут потреблять всего 1МБ памяти.
Оглавление
Direct Exchange
Direct exchange — используется, когда нужно доставить сообщение в определенные очереди. Сообщение публикуется в обменник с определенным ключом маршрутизации и попадает во все очереди, которые связаны с этим обменником аналогичным ключом маршрутизации. Ключ маршрутизации — это строка. Поиск соответствия происходит при помощи проверки строк на эквивалентность.
Графическое представление потока сообщений:
В rabbitmq существует понятие обменник по умолчанию. Это direct exchange без имени. Если применяется обменник по умолчанию, то сообщение будет маршрутизироваться в очередь с именем равным ключу маршрутизации сообщения.
Topic Exchange
Графическое представление потока сообщений:
Поиск соответствия шаблону осуществляется, начиная с корня и следуя сверху вниз.
Fanout Exchange
Fanout exchange – все сообщения доставляются во все очереди даже если в сообщении задан ключ маршрутизации.
Графическое представление потока сообщений:
Headers Exchange
Графическое представление потока сообщений:
Consistent-Hashing Exchange
Эквивалентный вес очередей – говорит о том, что в каждую очередь придет примерно одинаковое количество сообщений (каждое сообщение будет помещено только в одну очередь). Полной гарантии равномерного распределения сообщений нет.
Графическое представление потока сообщений:
Должен помогать, когда пропускная способность потребителя нуждается в росте более высоком чем решение с несколькими потребителями, использующими одну очередь.
Комбинирование обменников (E2E)
Графическое представление потока сообщений:
За счет E2E мы можем найти правильную масштабируемую конфигурацию, которая отвечает как текущим, так и растущим требованиям.
Создание Exchange
Пример создания exchange при помощи RabbitMQ.Client:
Обменник должен быть создан перед публикацией сообщений. Если вы опубликуете сообщение в какой-то не существующий обменник — RabbitMQ тихо удалит его.
Создание Exchange через графический интерфейс
Заключение
При разработке системы удобно описывать топологию маршрутизации при помощи графа. Но прежде чем начать строить граф стоит выделить пути с большим трафиком, т.к. именно они требуют более высокую пропускную способность (производительность). Далее можно классифицировать трафик. И уже потом приступить к построению.
Комбинации различных exchange должна помочь найти правильную масштабируемую конфигурацию, которая отвечает как текущим, так и растущим требованиям системы.
Количество exchange и очередей должно быть минимально по сравнению с количеством маршрутов.
В следующей статье начнем разбираться подробнее с Queues и Bindings.
В данном разделе опишем обменник кодом на C#, так если бы нам требовалось разработать библиотеку. Возможно это будет полезно для восприятия.
Part 4: RabbitMQ Exchanges, routing keys and bindings
Last updated: 2019-09-24
What is an exchange? What are routing keys and bindings? How are exchanges and queues associated with each other? When should I use them and how? This article explains the different types of exchanges in RabbitMQ and scenarios for how to use them.
Messages are not published directly to a queue. Instead, the producer sends messages to an exchange. Exchanges are message routing agents, defined by the virtual host within RabbitMQ. An exchange is responsible for routing the messages to different queues with the help of header attributes, bindings, and routing keys.
A binding is a «link» that you set up to bind a queue to an exchange.
The routing key is a message attribute the exchange looks at when deciding how to route the message to queues (depending on exchange type).
Exchanges, connections, and queues can be configured with parameters such as durable, temporary, and auto delete upon creation. Durable exchanges survive server restarts and last until they are explicitly deleted. Temporary exchanges exist until RabbitMQ is shut down. Auto-deleted exchanges are removed once the last bound object is unbound from the exchange.
In RabbitMQ, there are four different types of exchanges that route the message differently using different parameters and bindings setups. Clients can create their own exchanges or use the predefined default exchanges which are created when the server starts for the first time.
Standard RabbitMQ message flow
Exchange types
Direct Exchange
A direct exchange delivers messages to queues based on a message routing key. The routing key is a message attribute added to the message header by the producer. Think of the routing key as an «address» that the exchange is using to decide how to route the message. A message goes to the queue(s) with the binding key that exactly matches the routing key of the message.
The direct exchange type is useful to distinguish messages published to the same exchange using a simple string identifier.
The default exchange AMQP brokers must provide for the direct exchange is «amq.direct».
Imagine that queue A (create_pdf_queue) in the image below (Direct Exchange Figure) is bound to a direct exchange (pdf_events) with the binding key pdf_create. When a new message with routing key pdf_create arrives at the direct exchange, the exchange routes it to the queue where the binding_key = routing_key, in the case to queue A (create_pdf_queue).
Scenario 1
Scenario 2
Example
Example: A message with routing key pdf_log is sent to the exchange pdf_events. The messages is routed to pdf_log_queue because the routing key (pdf_log) matches the binding key (pdf_log).
If the message routing key does not match any binding key, the message is discarded.
Default exchange
The default exchange is a pre-declared direct exchange with no name, usually referred by an empty string. When you use default exchange, your message is delivered to the queue with a name equal to the routing key of the message. Every queue is automatically bound to the default exchange with a routing key which is the same as the queue name.
Topic Exchange
Topic exchanges route messages to queues based on wildcard matches between the routing key and the routing pattern, which is specified by the queue binding. Messages are routed to one or many queues based on a matching between a message routing key and this pattern.
The routing key must be a list of words, delimited by a period (.). Examples are agreements.us and agreements.eu.stockholm which in this case identifies agreements that are set up for a company with offices in lots of different locations. The routing patterns may contain an asterisk (“*”) to match a word in a specific position of the routing key (e.g., a routing pattern of «agreements.*.*.b.*» only match routing keys where the first word is «agreements» and the fourth word is «b»). A pound symbol (“#”) indicates a match of zero or more words (e.g., a routing pattern of «agreements.eu.berlin.#» matches any routing keys beginning with «agreements.eu.berlin»).
The consumers indicate which topics they are interested in (like subscribing to a feed for an individual tag). The consumer creates a queue and sets up a binding with a given routing pattern to the exchange. All messages with a routing key that match the routing pattern are routed to the queue and stay there until the consumer consumes the message.
The default exchange AMQP brokers must provide for the topic exchange is «amq.topic».
Scenario 1
The image to the right shows an example where consumer A is interested in all the agreements in Berlin.
Scenario 2
Consumer B is interested in all the agreements.
Scenario 3
Consumer C is interested in all agreements for European head stores.
Example
A message with routing key agreements.eu.berlin is sent to the exchange agreements. The messages are routed to the queue berlin_agreements because the routing pattern of «agreements.eu.berlin.#» matches the routing keys beginning with «agreements.eu.berlin». The message is also routed to the queue all_agreements because the routing key (agreements.eu.berlin) matches the routing pattern (agreements.#).
Fanout Exchange
A fanout exchange copies and routes a received message to all queues that are bound to it regardless of routing keys or pattern matching as with direct and topic exchanges. The keys provided will simply be ignored.
Fanout exchanges can be useful when the same message needs to be sent to one or more queues with consumers who may process the same message in different ways.
The image to the right (Fanout Exchange) shows an example where a message received by the exchange is copied and routed to all three queues bound to the exchange. It could be sport or weather updates that should be sent out to each connected mobile device when something happens, for instance.
The default exchange AMQP brokers must provide for the topic exchange is «amq.fanout».
Scenario 1
Example
A message is sent to the exchange sport_news. The message is routed to all queues (Queue A, Queue B, Queue C) because all queues are bound to the exchange. Provided routing keys are ignored.
Headers Exchange
A headers exchange routes messages based on arguments containing headers and optional values. Headers exchanges are very similar to topic exchanges, but route messages based on header values instead of routing keys. A message matches if the value of the header equals the value specified upon binding.
A special argument named «x-match», added in the binding between exchange and queue, specifies if all headers must match or just one. Either any common header between the message and the binding count as a match, or all the headers referenced in the binding need to be present in the message for it to match. The «x-match» property can have two different values: «any» or «all», where «all» is the default value. A value of «all» means all header pairs (key, value) must match, while value of «any» means at least one of the header pairs must match. Headers can be constructed using a wider range of data types, integer or hash for example, instead of a string. The headers exchange type (used with the binding argument «any») is useful for directing messages which contain a subset of known (unordered) criteria.
The default exchange AMQP brokers must provide for the topic exchange is «amq.headers».
Example
Scenario 1
Message 1 is published to the exchange with header arguments (key = value): «format = pdf», «type = report».
Message 1 is delivered to Queue A because all key/value pairs match, and Queue B since «format = pdf» is a match (binding rule set to «x-match =any»).
Scenario 2
Message 2 is published to the exchange with header arguments of (key = value): «format = pdf».
Message 2 is only delivered to Queue B. Because the binding of Queue A requires both «format = pdf» and «type = report» while Queue B is configured to match any key-value pair (x-match = any) as long as either «format = pdf» or «type = log» is present.
Scenario 3
Message 3 is published to the exchange with header arguments of (key = value): «format = zip», «type = log».
Message 3 is delivered to Queue B since its binding indicates that it accepts messages with the key-value pair «type = log», it doesn’t mind that «format = zip» since «x-match = any».
Queue C doesn’t receive any of the messages since its binding is configured to match all of the headers («x-match = all») with «format = zip», «type = pdf». No message in this example lives up to these criterias.
It’s worth noting that in a header exchange, the actual order of the key-value pairs in the message is irrelevant.
Dead Letter Exchange
If no matching queue can be found for the message, the message is silently dropped. RabbitMQ provides an AMQP extension known as the «Dead Letter Exchange», which provides the functionality to capture messages that are not deliverable.