diff --git a/savenkov_alexander_lab_4/.idea/.gitignore b/savenkov_alexander_lab_4/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/savenkov_alexander_lab_4/.idea/discord.xml b/savenkov_alexander_lab_4/.idea/discord.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/savenkov_alexander_lab_4/.idea/inspectionProfiles/profiles_settings.xml b/savenkov_alexander_lab_4/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/savenkov_alexander_lab_4/.idea/misc.xml b/savenkov_alexander_lab_4/.idea/misc.xml new file mode 100644 index 0000000..fe43ca6 --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/savenkov_alexander_lab_4/.idea/modules.xml b/savenkov_alexander_lab_4/.idea/modules.xml new file mode 100644 index 0000000..593b461 --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/savenkov_alexander_lab_4/.idea/savenkov_alexander_lab_4.iml b/savenkov_alexander_lab_4/.idea/savenkov_alexander_lab_4.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/savenkov_alexander_lab_4/.idea/savenkov_alexander_lab_4.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/savenkov_alexander_lab_4/README.md b/savenkov_alexander_lab_4/README.md new file mode 100644 index 0000000..874f710 --- /dev/null +++ b/savenkov_alexander_lab_4/README.md @@ -0,0 +1,69 @@ +# Лабораторная работа №4 - Работа с брокером сообщений + +Цель: изучение проектирования приложений при помощи брокера сообщений. + +Задачи: + +Необходимо выбрать предметную область и разработать следующие приложения: + +Publisher. Программа, которая создаёт один exchange с типом fanout. Программа должна раз в секунду генерировать сообщения в журнал событий согласно вашей предметной области. Например, событие "пришёл заказ" или "сообщение от пользователя" или "необходимо создать отчёт". +Consumer 1. Программа, которая создаёт под себя отдельную не анонимную (!) очередь (queue) (то есть имя queue НЕ пустая строка), создаёт binding на exchange и начинает принимать сообщения (consume). Программа должна обрабатывать сообщения 2-3 секунды. Можно реализовать через обычный Thread.Sleep (для C#). +Consumer 2. Аналогично Consumer 1, только сообщения необходимо обрабатывать моментально. Только имя очереди должно отличаться от Consumer 1. +Далее необходимо собрать и запустить приложения одновременно по одному экземпляру. + +Сделать в отчёте вывод о скорости обработки consumer-ами событий от publisher-а. Для этого можно посмотреть заполненность созданных очередей. А для этого можно использовать скриншот из RabbitMQ Management UI. + +Запустить несколько копий Consumer 1. Проверить заново заполненность очередей через UI. + +# Publisher +

+

Код Publisher
+ +

+

+

Работа Publisher
+ +

+ +# Consumer 1 + +

+

Код Consumer 1
+ +

+

+

Работа Consumer 1
+ +

+ +# Consumer 2 + +

+ + +

+

+

Работа Consumer 2
+ +

+ +# RabbitMQ Management UI + +

+

До запусков Consumer
+ +

+

+

После запуска Consumer 1
+ +

+

+

После запуска Consumer 2
+ +

+ +Вывод: по данным об очередях с RabbitMQ Management UI видно, что второй Consumer работает быстрее и ограничен лишь скоростью отправки сообщений, но если скорость отправки сообщений не будет ограничена, то возникает риск пропуска сообщений, а также такой метод сильнее нагружает систему и усложняет отслеживания работоспособности системы, что может привести к сбоям. + +# Видео + +Видео с разбором лабораторной работы - https://youtu.be/8GOG8MyPkO4 diff --git a/savenkov_alexander_lab_4/inventory_consumer.py b/savenkov_alexander_lab_4/inventory_consumer.py new file mode 100644 index 0000000..85d3958 --- /dev/null +++ b/savenkov_alexander_lab_4/inventory_consumer.py @@ -0,0 +1,34 @@ +import pika +import time + +def process_inventory_event(ch, method, properties, body): + decoded_message = body.decode('utf-8') + print(f" [x] Processing Inventory Event: {decoded_message}") + time.sleep(2) + print(" [x] Done") + ch.basic_ack(delivery_tag=method.delivery_tag) + +def main(): + # Устанавливаем соединение с сервером RabbitMQ + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + # Объявляем exchange с типом 'fanout' + channel.exchange_declare(exchange='events', exchange_type='fanout') + + # Создаем очередь с уникальным именем + result = channel.queue_declare(queue='', exclusive=True) + queue_name = result.method.queue + + # Привязываем очередь к exchange + channel.queue_bind(exchange='events', queue=queue_name) + + # Указываем, как обрабатывать сообщения при получении + channel.basic_consume(queue=queue_name, on_message_callback=process_inventory_event) + + print(' [*] Waiting for Inventory Events. To exit press CTRL+C') + # Запускаем бесконечный цикл получения и обработки сообщений + channel.start_consuming() + +if __name__ == '__main__': + main() diff --git a/savenkov_alexander_lab_4/order_processing_consumer.py b/savenkov_alexander_lab_4/order_processing_consumer.py new file mode 100644 index 0000000..3e222ba --- /dev/null +++ b/savenkov_alexander_lab_4/order_processing_consumer.py @@ -0,0 +1,34 @@ +import pika +import time + +def process_order_event(ch, method, properties, body): + decoded_message = body.decode('utf-8') + print(f" [x] Processing Order Event: {decoded_message}") + # No delay for Consumer 2 + print(" [x] Done") + ch.basic_ack(delivery_tag=method.delivery_tag) + +def main(): + # Устанавливаем соединение с сервером RabbitMQ + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + # Объявляем exchange с типом 'fanout' + channel.exchange_declare(exchange='events', exchange_type='fanout') + + # Создаем очередь с уникальным именем + result = channel.queue_declare(queue='', exclusive=True) + queue_name = result.method.queue + + # Привязываем очередь к exchange + channel.queue_bind(exchange='events', queue=queue_name) + + # Указываем, как обрабатывать сообщения при получении + channel.basic_consume(queue=queue_name, on_message_callback=process_order_event) + + print(' [*] Waiting for Order Events. To exit press CTRL+C') + # Запускаем бесконечный цикл получения и обработки сообщений + channel.start_consuming() + +if __name__ == '__main__': + main() diff --git a/savenkov_alexander_lab_4/publisher.py b/savenkov_alexander_lab_4/publisher.py new file mode 100644 index 0000000..a73d738 --- /dev/null +++ b/savenkov_alexander_lab_4/publisher.py @@ -0,0 +1,26 @@ +import pika +import time +import random + +def generate_order_event(channel): + order_id = random.randint(1, 1000) + event = f"Поступил новый заказ #{order_id}" + message = f"Событие: {event}" + channel.basic_publish(exchange='events', routing_key='', body=message) + print(f" [x] Sent: {message}") + +def main(): + # Устанавливаем соединение с сервером RabbitMQ + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + # Объявляем exchange с типом 'fanout' + channel.exchange_declare(exchange='events', exchange_type='fanout') + + # В бесконечном цикле генерируем и отправляем события в RabbitMQ + while True: + generate_order_event(channel) + time.sleep(1) + +if __name__ == '__main__': + main() diff --git a/savenkov_alexander_lab_4/screens/img1.png b/savenkov_alexander_lab_4/screens/img1.png new file mode 100644 index 0000000..959c42d Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img1.png differ diff --git a/savenkov_alexander_lab_4/screens/img2.png b/savenkov_alexander_lab_4/screens/img2.png new file mode 100644 index 0000000..d59368f Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img2.png differ diff --git a/savenkov_alexander_lab_4/screens/img3.png b/savenkov_alexander_lab_4/screens/img3.png new file mode 100644 index 0000000..02e5bad Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img3.png differ diff --git a/savenkov_alexander_lab_4/screens/img4.png b/savenkov_alexander_lab_4/screens/img4.png new file mode 100644 index 0000000..e963b1f Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img4.png differ diff --git a/savenkov_alexander_lab_4/screens/img5.png b/savenkov_alexander_lab_4/screens/img5.png new file mode 100644 index 0000000..c27847f Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img5.png differ diff --git a/savenkov_alexander_lab_4/screens/img6.png b/savenkov_alexander_lab_4/screens/img6.png new file mode 100644 index 0000000..d6320de Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img6.png differ diff --git a/savenkov_alexander_lab_4/screens/img7.png b/savenkov_alexander_lab_4/screens/img7.png new file mode 100644 index 0000000..d6253ff Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img7.png differ diff --git a/savenkov_alexander_lab_4/screens/img8.png b/savenkov_alexander_lab_4/screens/img8.png new file mode 100644 index 0000000..60fbd5c Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img8.png differ diff --git a/savenkov_alexander_lab_4/screens/img9.png b/savenkov_alexander_lab_4/screens/img9.png new file mode 100644 index 0000000..ac4d40a Binary files /dev/null and b/savenkov_alexander_lab_4/screens/img9.png differ