DAS_2023_1/arutunyan_dmitry_lab_4
2024-01-17 22:26:54 +04:00
..
hello-world arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
publish-subscribe arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
sushi-bar arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
work-queues arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
diag1.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
diag2.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
diag3.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
prog1.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
prog2.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
prog3.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
README.md arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
rep1.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00
rep2.png arutunyan_dmitry_lab_4 is ready 2024-01-17 22:26:54 +04:00

Лабораторная работа 4. Вариант 4.

Задание

Изучить проектирования приложений при помощи брокера сообщений.

  • Установить брокер сообщений RabbitMQ,
  • Пройти первые 3 урока из RabbitMQ Tutorials,
  • Продемонстрировать работу брокера сообщений.

Как запустить

Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать:

python publisher.py
python consumer1.py
python consumer2.py

Результат работы программы будет выведен в консоль.

Используемые технологии

  • Брокер сообщений RabbitMQ - программная система, реализующая протокол AMQP (Advanced Message Queuing Protocol), который представляет собой стандартный протокол обмена сообщениями между приложениями. RabbitMQ работает на основе модели "производитель-потребитель" (producer-consumer), где приложения, называемые "производителями", создают и отправляют сообщения в очередь, а другие приложения, называемые "потребителями", получают и обрабатывают эти сообщения из очереди. RabbitMQ обеспечивает надежную доставку сообщений, сохраняя их в очереди до тех пор, пока они не будут получены и обработаны потребителями.
  • Библиотека pika, обеспечивающая полную поддержку протокола AMQP (Advanced Message Queuing Protocol), который является стандартом для обмена сообщениями в системах очередей сообщений. Благодаря этой библиотеке возможно создание и настройка связи между компонентами системы, обмен сообщениями и управление очередями, используя простой и понятный API.

Описание работы

Выполнение RabbitMQ Tutorials

Урок "Hello World!"

В данном уроке рассматриваются две небольшие программы на Python; производитель (отправитель), который отправляет одно сообщение, и потребитель (получатель), который получает сообщения "Привет, мир" и распечатывает их.

Результат выполнения программ:

Урок "Work queues"

В данном уроке рассматривается создание рабочей очереди, которая будет использоваться для распределения трудоемких задач между несколькими рабочими.

Результат выполнения программ:

Урок "Publish/Subscribe"

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

Таким образом, в данном уроке рассматривается реализация шаблока "публикация / подписка".

Результат выполнения программ:

Выполнение демонстрационного приложения

В качестве предметной области была выбрана тематика курсовой работы "Суши-бар".

В таком случае, publisher раз в секунду отправляет сообщение по состоянию элементов заказа, на которое consumer1 и consumer2 необходимо отреагировать.

logs = ["get address", "get order", "get pavement", "order done"]

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
exchange_name = 'logs'
channel.exchange_declare(exchange=exchange_name, exchange_type='fanout')
print(' [*] Started. To exit press CTRL+C')

while 1:
    log = random.choice(logs)
    channel.basic_publish(exchange=exchange_name, routing_key='', body=log)
    print(f" [x] Published: {log}")
    time.sleep(1)

Данные сообщение транслируются на обе очереди подписчиков: slow-queue и fast-queue. consumer1 принимает сообшения в очередь slow-queue и реагирует на них (обрабатывает) в течении 2-3 секунд.

def message_manager(channel, queue_name, exchange_name):
    channel.queue_declare(queue=queue_name)
    channel.queue_bind(exchange=exchange_name, queue=queue_name)

    def callback(ch, method, properties, body):
        task = body.decode()
        print(f" [x] Received : {task}")
        time.sleep(random.randint(2, 3))
        if task == "get address":
            print(" [x] Address set")
        elif task == "get order":
            print(" [x] Order sent to preparation")
        elif task == "get pavement":
            print(" [x] Bank account checked")
        else:
            print(" [x] Order sent to a delivery")
        ch.basic_ack(delivery_tag=method.delivery_tag)

    channel.basic_consume(queue=queue_name, on_message_callback=callback)
    print("[*] Waiting for messages. To exit press CTRL+C")
    channel.start_consuming()


connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
exchange_name = 'logs'
queue_name = 'slow-queue'

consumer_thread = threading.Thread(target=message_manager, args=(channel, queue_name, exchange_name))
consumer_thread.start()
consumer_thread.join()

consumer2 принимает сообшения в очередь fast-queue и реагирует на них (обрабатывает) без задержек.

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
exchange_name = 'logs'
queue_name = 'fast-queue'

channel.queue_declare(queue=queue_name)
channel.queue_bind(exchange=exchange_name, queue=queue_name)


def callback(ch, method, properties, body):
    task = body.decode()
    print(f" [x] Received : {task}")
    if task == "get address":
        print(" [x] Address set")
    elif task == "get order":
        print(" [x] Order sent to preparation")
    elif task == "get pavement":
        print(" [x] Bank account checked")
    else:
        print(" [x] Order sent to a delivery")
    ch.basic_ack(delivery_tag=method.delivery_tag)


channel.basic_consume(queue=queue_name, on_message_callback=callback)
print("[*] Waiting for messages. To exit press CTRL+C")
channel.start_consuming()

Работа программы. Обзор скорости обработки сообщений

В первом случае, запустим по одному экземпляру каждого приложения. Проверим состояния очередей каждого из consumer:

Согласно данныи RabbitMQ, задачи в очереди slow-queue исполнителя consumer1 накапливаются линейно, поскольку данный исполнитель обрабатывает задачи с задержкой. Задачи в очереди fast-queue исполнителя consumer2 не накапливаются, т.к. данный исполнитель выполняет задачи мгновенно.

Во втором случае, запустим исполнитель consumer1 в 3х экземплярах и проверим состояние очереди slow-queue:

Как можно заметить, в данной конфигурации удалось добиться постоянного количества задач в очереди slow-queue - 2-3 задачи. Это обусловлено тем, что принимаемые consumer1 задачи равномерно распределяются по 3м исполнителям и успевают обрабатываться ими до накопления задач от publisher.

Вывод

Таким образом, RabbitMQ может иметь применение в распределённых системах в качестве узла обмена сообщениями между микросервисами для распределения и адресации задач между ними, а также обмеспечивает управление данными процессами.

Видео

https://youtu.be/T0lIQIHTenY