diff --git a/antonov_dmitry_lab4/README.md b/antonov_dmitry_lab4/README.md new file mode 100644 index 0000000..0c48996 --- /dev/null +++ b/antonov_dmitry_lab4/README.md @@ -0,0 +1,67 @@ +# Лабораторная работа №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. + +# Запуск + +Проект запускается в ide просто по нажатию у питон файла на функцию мейн. +Нужно последовательно запустить функцию мейн у файлов app.py, consumer1.py, consumer2.py. +Очередь сообщений запускается такой командой +docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management + +# Описание работы: +Развернули два приложения +Сервисы используем из предыдущей работы +Предметная область - врачи и пациенты + +1. Consumer 1 - врач 1: +2. Consumer 2 - врач 2: + +Оба врача принимают пациентов. + +Flask-приложение с RabbitMQ, использующего библиотеку pika для publisher и для consumers. +Надо обязательно вызвать метод publish, иначе никакого приема пациентов не начнется. +Приложение Flask (app.py), для источника пациентов (publisher) и двух врачей-потребителей (consumer1.py и consumer2.py). +Запускаем приложение Flask и обоих потребителей запускаем отдельно в разных терминалах. +Consumer ы будут прослушивать сообщения, опубликованные publisher ом. +

+

Главное приложение источник приема пациентов
+ +

+

+

Прибытие пациентов
+ +

+

+

RabbitMQ
+ +

+

+

Врач 1
+ +

+

+

Врач 2
+ +

+

+

Отчет ui
+ +

+ + +# Ссылка на видео +https://disk.yandex.ru/i/-6Ecl5T28IGmFA + diff --git a/antonov_dmitry_lab4/img.png b/antonov_dmitry_lab4/img.png new file mode 100644 index 0000000..caa83b1 Binary files /dev/null and b/antonov_dmitry_lab4/img.png differ diff --git a/antonov_dmitry_lab4/rabbitmq/app.py b/antonov_dmitry_lab4/rabbitmq/app.py new file mode 100644 index 0000000..ebf9b8b --- /dev/null +++ b/antonov_dmitry_lab4/rabbitmq/app.py @@ -0,0 +1,19 @@ +from flask import Flask, render_template, request +from publisher import publish_messages + +app = Flask(__name__) + + +@app.route('/') +def index(): + return "это publisher" + + +@app.route('/publish', methods=['GET']) +def publish(): + publish_messages() + return 'Начало приема пациентов' + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/antonov_dmitry_lab4/rabbitmq/consumer1.py b/antonov_dmitry_lab4/rabbitmq/consumer1.py new file mode 100644 index 0000000..49b9ff3 --- /dev/null +++ b/antonov_dmitry_lab4/rabbitmq/consumer1.py @@ -0,0 +1,26 @@ +import pika + + +def callback(ch, method, properties, body): + print("Врач 1 принимает пациента '{}'".format(body.decode())) + + +def consume_messages(): + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + exchange_name = 'logs' + channel.queue_declare(queue='example_queue') + channel.queue_bind(exchange=exchange_name, queue='example_queue') + channel.basic_consume(queue='example_queue', on_message_callback=callback, auto_ack=True) + print('Врач 1 ожидает приема') + try: + channel.start_consuming() + except KeyboardInterrupt: + print('Прервано. Останавливаем прием...') + channel.stop_consuming() + connection.close() + + +if __name__ == '__main__': + consume_messages() diff --git a/antonov_dmitry_lab4/rabbitmq/consumer2.py b/antonov_dmitry_lab4/rabbitmq/consumer2.py new file mode 100644 index 0000000..87bf4d9 --- /dev/null +++ b/antonov_dmitry_lab4/rabbitmq/consumer2.py @@ -0,0 +1,26 @@ +import pika + + +def callback(ch, method, properties, body): + print("Врач 2 принимает пациента '{}'".format(body.decode())) + + +def consume_messages(): + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + exchange_name = 'logs' + channel.queue_declare(queue='example_queue') + channel.queue_bind(exchange=exchange_name, queue='example_queue') + channel.basic_consume(queue='example_queue', on_message_callback=callback, auto_ack=True) + print(' Врач 2 ожидает пациента') + try: + channel.start_consuming() + except KeyboardInterrupt: + print('Врач 2 прекращает прием') + channel.stop_consuming() + connection.close() + + +if __name__ == '__main__': + consume_messages() diff --git a/antonov_dmitry_lab4/rabbitmq/publisher.py b/antonov_dmitry_lab4/rabbitmq/publisher.py new file mode 100644 index 0000000..c1e7040 --- /dev/null +++ b/antonov_dmitry_lab4/rabbitmq/publisher.py @@ -0,0 +1,19 @@ +import pika +import time + + +def publish_messages(): + connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) + channel = connection.channel() + + exchange_name = 'logs' + channel.exchange_declare(exchange=exchange_name, exchange_type='fanout') + channel.queue_declare(queue='example_queue') + # Отдаем сообщение в 'logs' exchange каждую секунду + while True: + message = "Пациент прибыл" # Сообщение + channel.basic_publish(exchange='logs', routing_key='', body=message) + print(f"Отправлено сообщение: {message}") + time.sleep(1) + print("Отправлено '{}'".format(message)) + connection.close() diff --git a/antonov_dmitry_lab4/screens/img.png b/antonov_dmitry_lab4/screens/img.png new file mode 100644 index 0000000..de6a521 Binary files /dev/null and b/antonov_dmitry_lab4/screens/img.png differ diff --git a/antonov_dmitry_lab4/screens/img_1.png b/antonov_dmitry_lab4/screens/img_1.png new file mode 100644 index 0000000..999b42e Binary files /dev/null and b/antonov_dmitry_lab4/screens/img_1.png differ diff --git a/antonov_dmitry_lab4/screens/img_2.png b/antonov_dmitry_lab4/screens/img_2.png new file mode 100644 index 0000000..e114bfa Binary files /dev/null and b/antonov_dmitry_lab4/screens/img_2.png differ diff --git a/antonov_dmitry_lab4/screens/img_3.png b/antonov_dmitry_lab4/screens/img_3.png new file mode 100644 index 0000000..5cafb2d Binary files /dev/null and b/antonov_dmitry_lab4/screens/img_3.png differ diff --git a/antonov_dmitry_lab4/screens/img_4.png b/antonov_dmitry_lab4/screens/img_4.png new file mode 100644 index 0000000..caa83b1 Binary files /dev/null and b/antonov_dmitry_lab4/screens/img_4.png differ diff --git a/antonov_dmitry_lab4/screens/img_5.png b/antonov_dmitry_lab4/screens/img_5.png new file mode 100644 index 0000000..739eb31 Binary files /dev/null and b/antonov_dmitry_lab4/screens/img_5.png differ