RabbitMQ Tutorial на Python. Часть 1. (Перевод)

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

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

В RabbitMQ и технологии передачи сообщений используется некоторый жаргон.

Producing(отправка) - отправка сообщения.
Producer(поставщик) - программа, которая отправляет сообщения.
Queue(очередь) - имя почтового ящика, который живет в RabbitMQ. Хотя сообщения передаются через RabbitMQ и ваши приложения, они могут храниться только в очереди. Очередь ограничена только размером оперативной памяти и дисков на сервере, и по сути является большим буфером сообщений. Многие поставщики могут отправлять сообщения в одну очередь и многие потребители могут попытаться получить данные из этой очереди. Вот так выглядит очередь:
Consuming(получение) - получение сообщения.
Consumer(потребитель) - программа, которая основную часть времени ожидает получения сообщения:
Обратите внимание, что поставщик, потребитель и брокер не должны располагаться на одном хосте. И действительно в большинстве приложений они этого не делают.

Hello, World!
(с использованием pika 0.10.0)

В этой части урока мы напишем две небольших программы на Python: поставщик(отправитель), который будет отправлять одно сообщение, и потребитель(получатель), который получает сообщение и печатает его. Это будет сообщение "Hello World".

На приведенной ниже диаграмме P является нашим поставщиком, а C - потребителем. Поле посередине представляет собой очередь - буфер сообщений, который RabbitMQ хранит от имени потребителя.

Наш общий дизайн будет выглядеть так:
Поставщик отправляет сообщение "hello" в очередь. Потребитель получает сообщение из этой очереди.

RabbitMQ libraries
RabbitMQ использует AMQP версии 0.9.1, который является открытым протоколом общего назначения для обмена сообщениями. Существует несколько клиентов RabbitMQ написанных на разных языках. В этом уроке мы воспользуемся Pika, клиентом написанным на Python, рекомендованным командой RabbitMQ. Для установки вы можете использовать менеджер пакетов pip.

Отправка(sending).

Наша первая программа send.py отправит одно сообщение в очередь. Первое, что нам нужно сделать - установить соединение с сервером RabbitMQ.

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

Мы подключились к брокеру на локальной машине, поэтому в качестве параметра передан 'localhost'. Если бы мы захотели подключиться к брокеру, расположенному на другой машине, мы бы указали ее DNS-имя или IP-адрес.

Далее, перед отправкой нам необходимо убедиться, что очередь получателей существует. Если мы отправим сообщение в расположение, которое не существует, RabbitMQ просто отбросит сообщение. Давайте создадим очередь hello, до которой будет доставлено сообщение:

channel.queue_declare(queue='hello')

Это точка в подготовке для отправки сообщения. Наше первое сообщение будет содержать в себе строку 'Hello World!' и мы хотим отправить его в нашу очередь hello.

В RabbitMQ сообщение не может быть отправлено непосредственно в очередь, оно всегда должно проходить процедуру обмена. Но давайте не будем погружаться в детали - Вы можете больше узнать об обмене в третьей части наших уроков. Теперь нам нужно узнать, как нам использовать стандартный обмен, идентифицированный пустой строкой. Этот обмен особенный - он позволяет нам точно указать в какую очередь должно попасть сообщение. Имя очереди указывается в параметре routing_key:

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')
print(" [x] Sent 'Hello World!'")

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

connection.close()

Примечание переводчика: для установки сервера RabbitMQ перейдите по ссылке. Выберите платформу или загрузите пакет. Следуйте подробным инструкциям по установке согласно выбранному разделу.

Отправка не работает!
Если вы в первый раз используете RabbitMQ и не увидели сообщение об отправке ("Sent" message), у вас может возникнуть желание почесать затылок, задаваясь вопросом, что же сделано неправильно. Возможно брокер был запущен без необходимого количества свободного места на диске(по умолчанию ему необходимо как минимум 200 Mb свободного места на диске), и поэтому отказывается принимать сообщения. Проверьте логфайл(logfile) брокера, чтобы подтвердить эту догадку, и уменьшите лимит, если необходимо. Описание конфигурационного файла покажет вам как установить disk_free_limit.

Получение (Receiving)

Наша вторая программа receive.py будет получать сообщения из очереди и печатать их на экране. 

Снова, первое что нам нужно сделать это подключиться к серверу RabbitMQ. Код, ответственный за подключение к RabbitMQ тот же, что и ранее.

В следующем шаге, как и ранее, необходимо убедиться что очередь существует. Создание очереди с помощью queue_declare идемпотентно - мы можем запустить команду столько раз, сколько захотим, но очередь будет создана только один раз.

channel.queue_declare(queue='hello')

Вы можете спросить почему мы создаем очередь снова - мы же уже создавали ее в нашем предыдущем коде. Мы бы могли избежать этого, если бы были уверены, что очередь уже существует. Например, если программа send.py была запущена до этого. Но мы не можем быть уверены в том, какая из программ будет запущена первой. В таких случаях рекомендуется повторять создание очереди в обеих программах.

Список очередей

Вы можете посмотреть какие очереди существуют в RabbitMQ и сколько сообщений они содержат. Вы можете сделать это (как привилегированный пользователь) используя rabbitmqctl tool:

sudo rabbitmqctl list_queues

В Windows:

rabbitmqctl.bat list_queues

Получение сообщений из очереди является более сложным делом. Обработка осуществляется с применением callback функции к очереди. Всякий раз, когда мы получаем сообщение, callback функция вызывается из библиотеки Pika. В нашем случае эта функция напечатает на экране содержимое сообщения.

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)

Далее, нам необходимо сказать RabbitMQ что частный случай этой callback функции должен получать сообщения из нашей очереди "hello":

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)

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

Параметр no_ack будет описан позже.

И, наконец, мы вводим бесконечный цикл, который ожидает данные и запускает callback-и, когда это необходимо.


print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

Собираем все вместе

Полный исходный код send.py:

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()

Ссылка на исходный код send.py

Полный исходный код receive.py:

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

Ссылка на исходный код receive.py

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

python receive.py
# => [*] Waiting for messages. To exit press CTRL+C
# => [x] Received 'Hello World!'

Сейчас запустим поставщика(producer). Программа-поставщик будет останавливаться после каждого запуска:

python send.py
# => [x] Sent 'Hello World!'

Ура! Мы смогли отправить первое сообщение через RabbitMQ. Как вы могли заметить, программа receive.py не останавливается, она готова к приему дальнейших сообщений и может быть прервана через комбинацию клавиш Ctrl+C.

Попробуйте запустить send.py в новом терминале.

Мы научились отправлять и принимать сообщения из именованной очереди. Пришло время перейти к части 2 и построить простую очередь обработки.

Ссылка на оригинал статьи.

Комментарии

Отправить комментарий

Популярные сообщения из этого блога

RabbitMQ Tutorial на Python. Часть 2. (Перевод)

RabbitMQ Tutorial на Python. Часть 3. (Перевод)