RabbitMQ: примеры rabbitmqctl, rabbitmqadmin и хранение сообщений при рестарте сервера

By | 12/05/2018
 

Задача – запустить RabbitMQ сервер и создать сообщение, но таким образом, что бы оно сохранилось при рестарте сервера.

Документация по хранению данных – тут>>>.

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

Кроме того, для примера работы с rabbitmqctl и rabbitmqadmin выполним:

  1. создадим vhost
  2. создадим пользователя с доступом к этому вхосту
  3. создадим очередь в этом виртуалхосте
  4. создадим exchange для этой queue
  5. создадим binding

Подготовка RabbitMQ

RabbitMQ vhost

Документация – тут>>>.

Создаём виртуалхост:

root@ip-172-31-18-246:/home/admin# rabbitmqctl add_vhost examplevhost
Creating vhost "examplevhost" ...

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqctl list_vhosts
Listing vhosts ...
/
examplevhost

RabbitMQ user

Документация – тут>>>.

Создаём пользователя:

root@ip-172-31-18-246:/home/admin# rabbitmqctl add_user exampleuser examplepass
Creating user "exampleuser" ...

И права на созданный хост:

root@ip-172-31-18-246:/home/admin# rabbitmqctl set_permissions -p examplevhost exampleuser ".*" ".*" ".*"
Setting permissions for user "exampleuser" in vhost "examplevhost" ...

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass list queues
*** Access refused: /api/queues?columns=name,messages

Эм…

То же.

Проверяем лог – /var/log/rabbitmq/rabbit\@ip-172-31-18-246.log:

=WARNING REPORT==== 4-Dec-2018::15:18:26 ===
HTTP access denied: user ‘exampleuser’ – Not management user

Ах, да.

Добавляем тег “administrator“:

root@ip-172-31-18-246:/home/admin# rabbitmqctl set_user_tags exampleuser administrator
Setting tags for user "exampleuser" to [administrator] ...

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass list vhosts
+--------------+----------+
|     name     | messages |
+--------------+----------+
| /            | 1        |
| examplevhost |          |
+--------------+----------+

И очереди в нашем виртуахосте:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues
No items

RabbitMQ queues

Документация тут>>>, и хороший обзор – тут>>>.

Создаём очередь:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass declare queue --vhost=examplevhost name=examplequeue
queue declared

Ещё раз проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues
+--------------+----------+
|     name     | messages |
+--------------+----------+
| examplequeue | 0        |
+--------------+----------+

RabbitMQ exchanges

Примеры – тут>>>, описание тут>>>.

Создаём exchange:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass declare exchange --vhost=examplevhost  name="exampleexchange" type="direct"
exchange declared

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
| exampleexchange    | direct  |
+--------------------+---------+

RabbitMQ bindings

См. тут>>> и тут>>>.

Проверяем биндинги – сейчас тут один, дефолтный, который перенаправляет все сообщения с routing_key == examplequeue в очередь с именем examplequeue:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list bindings
+--------+--------------+--------------+
| source | destination  | routing_key  |
+--------+--------------+--------------+
|        | examplequeue | examplequeue |
+--------+--------------+--------------+

Добавляем новый:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass declare binding --vhost=examplevhost source="exampleexchange" destination_type="queue" destination="examplequeue" routing_key="examplekey"
binding declared

Что бы как-то отличать работу нашего биндинга от дефолтного – используем значение routing_key == examplekey.

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list bindings
+-----------------+--------------+--------------+
|     source      | destination  | routing_key  |
+-----------------+--------------+--------------+
|                 | examplequeue | examplequeue |
| exampleexchange | examplequeue | examplekey   |
+-----------------+--------------+--------------+

Отправляем сообщение:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass publish exchange=exampleexchange routing_key=examplekey payload="hello, world"
Message published

Проверяем очередь:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues
+--------------+----------+
|     name     | messages |
+--------------+----------+
| examplequeue | 1        |
+--------------+----------+

Получаем сообщение:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass get queue=examplequeue requeue=true
+-------------+-----------------+---------------+--------------+---------------+------------------+------------+-------------+
| routing_key |    exchange     | message_count |   payload    | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------------+---------------+--------------+---------------+------------------+------------+-------------+
| examplekey  | exampleexchange | 0             | hello, world | 12            | string           |            | False       |
+-------------+-----------------+---------------+--------------+---------------+------------------+------------+-------------+

Используем тут параметр requeue=true, что бы сообщение осталось в очереди.

Хранение сообщений при рестарте

А теперь – перезапускаем сервер:

root@ip-172-31-18-246:/home/admin# systemctl restart rabbitmq-server

И проверяем очередь пещё раз:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues
+--------------+----------+
|     name     | messages |
+--------------+----------+
| examplequeue | 0        |
+--------------+----------+

Или с дополнительными полями:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues vhost name messages
+--------------+--------------+----------+
|    vhost     |     name     | messages |
+--------------+--------------+----------+
| examplevhost | examplequeue | 0        |
+--------------+--------------+----------+

Сообщений == 0.

Что бы RabbitMQ сохранял сообщения – необходимо два изменения.

Первое – объявить очередь как durable:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass declare queue --vhost=examplevhost name=examplequeue durable=true
queue declared

Проверяем.

Добавляем -f (format) long, и -d (depth) 2:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass list queues -f long -d 2
--------------------------------------------------------------------------------
vhost: examplevhost
name: examplequeue
...
durable: True
...

Или через RabbitMQ WebUI:

Следующим – добавляем сообщение, но указываем delivery_mode == 2:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass publish exchange=exampleexchange routing_key=examplekey payload="hello, world" properties="{\"delivery_mode\": 2}"
Message published

Проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass list queues
+--------------+----------+
|     name     | messages |
+--------------+----------+
| examplequeue | 1        |
+--------------+----------+

Ребутаем RabbitMQ:

root@ip-172-31-18-246:/home/admin# systemctl restart rabbitmq-server

Ещё раз проверяем:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -u exampleuser -p examplepass list queues
+--------------+----------+
|     name     | messages |
+--------------+----------+
| examplequeue | 1        |
+--------------+----------+

Получаем его:

root@ip-172-31-18-246:/home/admin# rabbitmqadmin -V examplevhost -u exampleuser -p examplepass get queue=examplequeue requeue=true
+-------------+-----------------+---------------+--------------+---------------+------------------+-------------+
| routing_key |    exchange     | message_count |   payload    | payload_bytes | payload_encoding | redelivered |
+-------------+-----------------+---------------+--------------+---------------+------------------+-------------+
| examplekey  | exampleexchange | 0             | hello, world | 12            | string           | False       |
+-------------+-----------------+---------------+--------------+---------------+------------------+-------------+

Всё на месте.

Ссылки по теме

Persistence Configuration

How to persist messages during RabbitMQ broker restart?

Dabbling around Rabbit MQ persistence, durability & message routing

Configuring RabbitMQ Exchanges, Queues and Bindings: Part 1

Reasoning About Memory Use

Memory Alarms