diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..11a5d8e --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +main.py \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..74ac817 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..ae8ddd2 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/artamonova_tatyana_lab_1/README.md b/artamonova_tatyana_lab_1/README.md new file mode 100644 index 0000000..ee9977a --- /dev/null +++ b/artamonova_tatyana_lab_1/README.md @@ -0,0 +1,48 @@ +## Отчет по Docker Compose конфигурации + +### Краткое описание: + +Данная конфигурация Docker Compose запускает набор сервисов, необходимых для работы WordPress и MediaWiki. Она включает в себя: + +- **WordPress:** веб-сервис для блогов и CMS +- **MySQL:** база данных для хранения данных WordPress +- **RabbitMQ:** брокер сообщений для потенциального использования в будущем +- **MediaWiki:** вики-движок для создания и редактирования вики-страниц + +### Запуск лабораторной работы: + +1. Установить Docker и Docker Compose. +2. Сохранить конфигурацию в файл docker-compose.yml. +3. Запустить команду docker-compose up --build + +### Используемые технологии: + +- **Docker Compose:** инструмент для определения и запуска многоконтейнерных приложений. +- **Docker:** платформа для создания, развертывания и запуска контейнеров. +- **WordPress:** популярная платформа для создания блогов и CMS. +- **MySQL:** популярная система управления базами данных. +- **RabbitMQ:** брокер сообщений, используемый для асинхронного обмена сообщениями. +- **MediaWiki:** свободное программное обеспечение для создания и редактирования вики-страниц. + +### Функциональность: + +Конфигурация запускает следующие сервисы: + +- **WordPress:** работает на порту 8080, доступен по адресу http://localhost:8080. +- **MySQL:** предоставляет базу данных для WordPress и MediaWiki. +- **RabbitMQ:** работает на порту 5672, доступен по адресу http://localhost:15672 для управления. +- **MediaWiki:** работает на порту 8081, доступен по адресу http://localhost:8081. + +### Дополнительные сведения + +- **Volumes**: используются для хранения данных сервисов, чтобы они не терялись при перезапуске контейнеров. +- **Depends_on**: указывает на зависимость между сервисами, например, WordPress зависит от MySQL. +- **Restart policy**: определяет, как сервисы будут перезапускаться после сбоя. + +### Видео + +https://vk.com/video/@artamonovat?z=video212084908_456239356%2Fpl_212084908_-2 + +### Заключение: + +Данная конфигурация Docker Compose обеспечивает простой и удобный способ запуска и управления несколькими сервисами, связанными с WordPress и MediaWiki. Она позволяет разработчикам легко развертывать и управлять приложениями в изолированной среде. \ No newline at end of file diff --git a/artamonova_tatyana_lab_1/docker-compose.yml b/artamonova_tatyana_lab_1/docker-compose.yml new file mode 100644 index 0000000..432e8b1 --- /dev/null +++ b/artamonova_tatyana_lab_1/docker-compose.yml @@ -0,0 +1,61 @@ +version: '3.7' + +services: + wordpress: + image: wordpress:latest + ports: + - "8080:80" + volumes: + - wordpress_data:/var/www/html + environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_NAME: wordpress + WORDPRESS_DB_USER: wordpress + WORDPRESS_DB_PASSWORD: password + depends_on: + - db + restart: unless-stopped + + db: + image: mysql:latest + volumes: + - db_data:/var/lib/mysql + environment: + MYSQL_DATABASE: wordpress + MYSQL_USER: wordpress + MYSQL_PASSWORD: dbpassword + MYSQL_ROOT_PASSWORD: rootpassword + restart: unless-stopped + + rabbitmq: + image: rabbitmq:3-management + ports: + - "5672:5672" + - "15672:15672" + volumes: + - rabbitmq_data:/var/lib/rabbitmq + environment: + RABBITMQ_DEFAULT_USER: guest + RABBITMQ_DEFAULT_PASS: password + restart: unless-stopped + + mediawiki: + image: mediawiki:latest + ports: + - "8081:80" + volumes: + - mediawiki_data:/var/www/html + environment: + MW_DB_SERVER: db + MW_DB_NAME: mediawiki + MW_DB_USER: mediawiki + MW_DB_PASSWORD: mediawiki_password + depends_on: + - db + restart: unless-stopped + +volumes: + wordpress_data: + db_data: + rabbitmq_data: + mediawiki_data: diff --git a/artamonova_tatyana_lab_2/.gitignore b/artamonova_tatyana_lab_2/.gitignore new file mode 100644 index 0000000..79b0ca1 --- /dev/null +++ b/artamonova_tatyana_lab_2/.gitignore @@ -0,0 +1,5 @@ +*.pyc +__pycache__ +*.egg-info +*.dist-info +.DS_Store \ No newline at end of file diff --git a/artamonova_tatyana_lab_2/README.md b/artamonova_tatyana_lab_2/README.md new file mode 100644 index 0000000..dd594fd --- /dev/null +++ b/artamonova_tatyana_lab_2/README.md @@ -0,0 +1,22 @@ +## Лабораторная работа №2 +### Выполнила Артамонова Татьяна ПИбд-42 + +**Вариант 1: Программа 4 - Количество символов в именах файлов из каталога /var/data** + +- Формирует файл /var/result/data1.txt так, что каждая строка файла - количество символов в именах файлов из каталога /var/data. + +**Вариант 2: Программа 3 - Количество чисел в последовательности** + +- Ищет набольшее число из файла /var/result/data1.txt и сохраняет количество таких чисел из последовательности в /var/result/data2.txt. + +**Структура проекта:** + +1. В папках worker-1, worker-2 лежат выполняемые файлы .py и Dockerfile-ы с необходимым набором инструкций. +2. В папке data лежат файлы, длину имен которых нужно посчитать. +3. В папке result лежат файлы с результатами выполнения программ. data1.txt - результат выполнения main1.py (worker-1), data2.txt - результат выполнения main2.py (worker-2). Данные в data2 рассчитываются из данных data1. +4. Файл .gitignore - для указания, какие файлы отслеживать, а какие - нет. +5. docker-compose.yml - для определения и управления контейнерами Docker. + +**Команда для запуска** - docker-compose up --build + +**Ссылка на видео:** https://vk.com/artamonovat?z=video212084908_456239357%2Fvideos212084908%2Fpl_212084908_-2 \ No newline at end of file diff --git a/artamonova_tatyana_lab_2/data/exampleFile.txt b/artamonova_tatyana_lab_2/data/exampleFile.txt new file mode 100644 index 0000000..e69de29 diff --git a/artamonova_tatyana_lab_2/data/exampleFile123.txt b/artamonova_tatyana_lab_2/data/exampleFile123.txt new file mode 100644 index 0000000..e69de29 diff --git a/artamonova_tatyana_lab_2/data/exampleFile456.txt b/artamonova_tatyana_lab_2/data/exampleFile456.txt new file mode 100644 index 0000000..e69de29 diff --git a/artamonova_tatyana_lab_2/docker-compose.yml b/artamonova_tatyana_lab_2/docker-compose.yml new file mode 100644 index 0000000..c08293c --- /dev/null +++ b/artamonova_tatyana_lab_2/docker-compose.yml @@ -0,0 +1,22 @@ +services: + worker-1: + build: + context: ./worker-1 + volumes: + - ./worker-1:/app + - ./data:/var/data + - ./result:/var/result + depends_on: + - worker-2 + + worker-2: + build: + context: ./worker-2 + volumes: + - ./worker-2:/app + - ./data:/var/data + - ./result:/var/result + +volumes: + data: + result: diff --git a/artamonova_tatyana_lab_2/result/data1.txt b/artamonova_tatyana_lab_2/result/data1.txt new file mode 100644 index 0000000..9f05acf --- /dev/null +++ b/artamonova_tatyana_lab_2/result/data1.txt @@ -0,0 +1,3 @@ +15 +18 +18 diff --git a/artamonova_tatyana_lab_2/result/data2.txt b/artamonova_tatyana_lab_2/result/data2.txt new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/artamonova_tatyana_lab_2/result/data2.txt @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/artamonova_tatyana_lab_2/worker-1/Dockerfile b/artamonova_tatyana_lab_2/worker-1/Dockerfile new file mode 100644 index 0000000..732ed27 --- /dev/null +++ b/artamonova_tatyana_lab_2/worker-1/Dockerfile @@ -0,0 +1,14 @@ +# Используем образ Python 3.10-slim как основу для нашего контейнера. +# slim-версия образа более компактная, что делает контейнер меньше. +FROM python:3.10-slim + +# Устанавливаем рабочую директорию в контейнере как /app. +# Все последующие команды будут выполняться в этой директории. +WORKDIR /app + +# Копируем файл main1.py из текущей директории в директорию /app в контейнере. +COPY main1.py . + +# Определяем команду, которая будет выполняться при запуске контейнера. +# В данном случае запускается Python-скрипт main1.py. +CMD ["python", "main1.py"] diff --git a/artamonova_tatyana_lab_2/worker-1/main1.py b/artamonova_tatyana_lab_2/worker-1/main1.py new file mode 100644 index 0000000..c14ac98 --- /dev/null +++ b/artamonova_tatyana_lab_2/worker-1/main1.py @@ -0,0 +1,21 @@ +import os +import glob + +# Формирует файл data1.txt так, что каждая строка файла - кол-во символов в именах файла из каталога /data +def main(): + data_dir = "/var/data" + result_file = "/var/result/data1.txt" + + result_dir = os.path.dirname(result_file) + if not os.path.exists(result_dir): + os.makedirs(result_dir) + + files = glob.glob(os.path.join(data_dir, '*')) + + with open(result_file, 'w') as f: + for file in files: + filename = os.path.basename(file) + f.write(f"{len(filename)}\n") + +if __name__ == "__main__": + main() diff --git a/artamonova_tatyana_lab_2/worker-2/Dockerfile b/artamonova_tatyana_lab_2/worker-2/Dockerfile new file mode 100644 index 0000000..6e645de --- /dev/null +++ b/artamonova_tatyana_lab_2/worker-2/Dockerfile @@ -0,0 +1,14 @@ +# Используем образ Python 3.10-slim как основу для нашего контейнера. +# slim-версия образа более компактная, что делает контейнер меньше. +FROM python:3.10-slim + +# Устанавливаем рабочую директорию в контейнере как /app. +# Все последующие команды будут выполняться в этой директории. +WORKDIR /app + +# Копируем файл main2.py из текущей директории в директорию /app в контейнере. +COPY main2.py . + +# Определяем команду, которая будет выполняться при запуске контейнера. +# В данном случае запускается Python-скрипт main2.py. +CMD ["python", "main2.py"] diff --git a/artamonova_tatyana_lab_2/worker-2/main2.py b/artamonova_tatyana_lab_2/worker-2/main2.py new file mode 100644 index 0000000..ca477a1 --- /dev/null +++ b/artamonova_tatyana_lab_2/worker-2/main2.py @@ -0,0 +1,26 @@ +import os + +# Ищет наибольшее число из файла data1.txt и сохраняет количество таких чисел из последовательности в data2.txt +def main(): + data_file_path = "/var/result/data1.txt" + result_file_path = "/var/result/data2.txt" + + if not os.path.exists(data_file_path): + data_dir = os.path.dirname(data_file_path) + + if not os.path.exists(result_file_path): + result_dir = os.path.dirname(result_file_path) + + with open(data_file_path, 'r') as f: + numbers = [int(x.strip()) for x in f.read().splitlines()] + + max_number = max(numbers) + count = numbers.count(max_number) + + with open(result_file_path, 'w') as f: + f.write(str(count)) + + print(f"Количество наибольших чисел: {count}") + +if __name__ == "__main__": + main() diff --git a/bogdanov_dmitry_lab_4/README.md b/bogdanov_dmitry_lab_4/README.md new file mode 100644 index 0000000..1efa097 --- /dev/null +++ b/bogdanov_dmitry_lab_4/README.md @@ -0,0 +1,34 @@ +# Богданов Дмитрий ПИбд-42 +# Лабораторная работа №4 + + +## Предметная область: +Автоматизация работы теплицы + +## Результаты выполнения туториалов: + +- Первый туториал: +![изображение 1](./images/tut1.png) + +- Второй туториал: +![изображение 2](./images/tut2.png) + +- Третий туториал: +![изображение 3](./images/tut3.png) + + +## Данные из RabbitMQ: + +![изображение 1](./images/rmq1.png) +![изображение 2](./images/rmq2.png) +![изображение 3](./images/rmq3.png) +![изображение 3](./images/rmq4.png) + +### Вывод: +Из-за моментальной обработки сообщений в Consumer2, его очередь никогда не заполняется. +Consumer1 же тратит на обработку 2 секунды, из-за чего соответствующая очередь существенно заполняется при одном +запущенном экземпляре. +При нескольких запущенных экземплярах Consumer1 очередь заполняется существенно медленнее, и перестаёт заполняться совсем при определенном кол-ве запущенных экземпляров. + + +## [Видео](https://drive.google.com/file/d/1KWHHYWiK8OX48OfhDnEKDtMz-Umfs0uj/view?usp=sharing) \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/Sample Program/consumer1.py b/bogdanov_dmitry_lab_4/Sample Program/consumer1.py new file mode 100644 index 0000000..7defb87 --- /dev/null +++ b/bogdanov_dmitry_lab_4/Sample Program/consumer1.py @@ -0,0 +1,27 @@ +import pika +import time + + +def callback(ch, method, properties, body): + print(f'Receiver 1: получено сообщение. {body.decode()}') + + time.sleep(3) + + print('Receiver 1 закончил обработку') + + +def consume_events_1(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) + channel = connection.channel() + + channel.queue_declare(queue='receiver1_queue') + channel.queue_bind(exchange='greenhouse_events', queue='receiver1_queue') + + channel.basic_consume(queue='receiver1_queue', on_message_callback=callback, auto_ack=True) + + print('Ожидание сообщения...') + channel.start_consuming() + + +if __name__ == "__main__": + consume_events_1() diff --git a/bogdanov_dmitry_lab_4/Sample Program/consumer2.py b/bogdanov_dmitry_lab_4/Sample Program/consumer2.py new file mode 100644 index 0000000..2151864 --- /dev/null +++ b/bogdanov_dmitry_lab_4/Sample Program/consumer2.py @@ -0,0 +1,24 @@ +import pika + + +def callback(ch, method, properties, body): + print(f'Receiver 2: получено сообщение. {body.decode()}') + + print('Receiver 2 закончил обработку') + + +def consume_events_2(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) + channel = connection.channel() + + channel.queue_declare(queue='receiver2_queue') + channel.queue_bind(exchange='greenhouse_events', queue='receiver2_queue') + + channel.basic_consume(queue='receiver2_queue', on_message_callback=callback, auto_ack=True) + + print('Ожидание сообщения...') + channel.start_consuming() + + +if __name__ == "__main__": + consume_events_2() diff --git a/bogdanov_dmitry_lab_4/Sample Program/publisher.py b/bogdanov_dmitry_lab_4/Sample Program/publisher.py new file mode 100644 index 0000000..cb5debe --- /dev/null +++ b/bogdanov_dmitry_lab_4/Sample Program/publisher.py @@ -0,0 +1,25 @@ +import pika +import time + +def publish_events(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) + channel = connection.channel() + + channel.exchange_declare(exchange='greenhouse_events', exchange_type='fanout') + + events = [ + "Влажность превысила верхнюю границу", + "Влажность упала за нижнюю границу", + "Полив начат", + "Полив остановлен" + ] + + while True: + event = events[int(time.time()) % len(events)] + channel.basic_publish(exchange='greenhouse_events', routing_key='', body=event) + print(f'Отправлено: {event}') + time.sleep(1) + + +if __name__ == "__main__": + publish_events() diff --git a/bogdanov_dmitry_lab_4/Tutorial 1/receive.py b/bogdanov_dmitry_lab_4/Tutorial 1/receive.py new file mode 100644 index 0000000..03b817d --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 1/receive.py @@ -0,0 +1,25 @@ +import pika, sys, os + +def main(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) + channel = connection.channel() + + channel.queue_declare(queue='hello') + + def callback(ch, method, properties, body): + print(f" [x] Received {body}") + + channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True) + + print(' [*] Waiting for messages. To exit press CTRL+C') + channel.start_consuming() + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print('Interrupted') + try: + sys.exit(0) + except SystemExit: + os._exit(0) diff --git a/bogdanov_dmitry_lab_4/Tutorial 1/send.py b/bogdanov_dmitry_lab_4/Tutorial 1/send.py new file mode 100644 index 0000000..64b411d --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 1/send.py @@ -0,0 +1,13 @@ +import pika + +connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) +channel = connection.channel() + +channel.queue_declare('hello') + +channel.basic_publish(exchange='', + routing_key='hello', + body='Hello world!') +print(" [x] Sent 'Hello world!'") + +connection.close() \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/Tutorial 2/new_task.py b/bogdanov_dmitry_lab_4/Tutorial 2/new_task.py new file mode 100644 index 0000000..5ed2d91 --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 2/new_task.py @@ -0,0 +1,19 @@ +import pika +import sys + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) +channel = connection.channel() + +channel.queue_declare(queue='task_queue', durable=True) + +message = ' '.join(sys.argv[1:]) or "Hello World!" +channel.basic_publish( + exchange='', + routing_key='task_queue', + body=message, + properties=pika.BasicProperties( + delivery_mode=pika.DeliveryMode.Persistent + )) +print(f" [x] Sent {message}") +connection.close() \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/Tutorial 2/worker.py b/bogdanov_dmitry_lab_4/Tutorial 2/worker.py new file mode 100644 index 0000000..d83d59a --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 2/worker.py @@ -0,0 +1,22 @@ +import pika +import time + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) +channel = connection.channel() + +channel.queue_declare(queue='task_queue', durable=True) +print(' [*] Waiting for messages. To exit press CTRL+C') + + +def callback(ch, method, properties, body): + print(f" [x] Received {body.decode()}") + time.sleep(body.count(b'.')) + print(" [x] Done") + ch.basic_ack(delivery_tag=method.delivery_tag) + + +channel.basic_qos(prefetch_count=1) +channel.basic_consume(queue='task_queue', on_message_callback=callback) + +channel.start_consuming() \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/Tutorial 3/emit_log.py b/bogdanov_dmitry_lab_4/Tutorial 3/emit_log.py new file mode 100644 index 0000000..a02a070 --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 3/emit_log.py @@ -0,0 +1,13 @@ +import pika +import sys + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) +channel = connection.channel() + +channel.exchange_declare(exchange='logs', exchange_type='fanout') + +message = ' '.join(sys.argv[1:]) or "info: Hello World!" +channel.basic_publish(exchange='logs', routing_key='', body=message) +print(f" [x] Sent {message}") +connection.close() \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/Tutorial 3/receive_logs.py b/bogdanov_dmitry_lab_4/Tutorial 3/receive_logs.py new file mode 100644 index 0000000..6363847 --- /dev/null +++ b/bogdanov_dmitry_lab_4/Tutorial 3/receive_logs.py @@ -0,0 +1,22 @@ +import pika + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost', port=5672, credentials=pika.PlainCredentials("user", "password"))) +channel = connection.channel() + +channel.exchange_declare(exchange='logs', exchange_type='fanout') + +result = channel.queue_declare(queue='', exclusive=True) +queue_name = result.method.queue + +channel.queue_bind(exchange='logs', queue=queue_name) + +print(' [*] Waiting for logs. To exit press CTRL+C') + +def callback(ch, method, properties, body): + print(f" [x] {body}") + +channel.basic_consume( + queue=queue_name, on_message_callback=callback, auto_ack=True) + +channel.start_consuming() \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/compose.yaml b/bogdanov_dmitry_lab_4/compose.yaml new file mode 100644 index 0000000..7e7c284 --- /dev/null +++ b/bogdanov_dmitry_lab_4/compose.yaml @@ -0,0 +1,12 @@ +version: '3.8' + +services: + rabbitmq: + image: rabbitmq:3-management + container_name: rabbitmq + environment: + RABBITMQ_DEFAULT_USER: user + RABBITMQ_DEFAULT_PASS: password + ports: + - "5672:5672" + - "15672:15672" \ No newline at end of file diff --git a/bogdanov_dmitry_lab_4/images/rmq1.png b/bogdanov_dmitry_lab_4/images/rmq1.png new file mode 100644 index 0000000..0f89de7 Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/rmq1.png differ diff --git a/bogdanov_dmitry_lab_4/images/rmq2.png b/bogdanov_dmitry_lab_4/images/rmq2.png new file mode 100644 index 0000000..916118c Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/rmq2.png differ diff --git a/bogdanov_dmitry_lab_4/images/rmq3.png b/bogdanov_dmitry_lab_4/images/rmq3.png new file mode 100644 index 0000000..e9529ad Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/rmq3.png differ diff --git a/bogdanov_dmitry_lab_4/images/rmq4.png b/bogdanov_dmitry_lab_4/images/rmq4.png new file mode 100644 index 0000000..4e1b089 Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/rmq4.png differ diff --git a/bogdanov_dmitry_lab_4/images/tut1.png b/bogdanov_dmitry_lab_4/images/tut1.png new file mode 100644 index 0000000..90be8e5 Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/tut1.png differ diff --git a/bogdanov_dmitry_lab_4/images/tut2.png b/bogdanov_dmitry_lab_4/images/tut2.png new file mode 100644 index 0000000..ce16eda Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/tut2.png differ diff --git a/bogdanov_dmitry_lab_4/images/tut3.png b/bogdanov_dmitry_lab_4/images/tut3.png new file mode 100644 index 0000000..847cddf Binary files /dev/null and b/bogdanov_dmitry_lab_4/images/tut3.png differ diff --git a/bogdanov_dmitry_lab_5/MatrixMult/main.py b/bogdanov_dmitry_lab_5/MatrixMult/main.py new file mode 100644 index 0000000..2913f9a --- /dev/null +++ b/bogdanov_dmitry_lab_5/MatrixMult/main.py @@ -0,0 +1,88 @@ +import random as rnd +import threading +import time +from multiprocessing import Pool + +def generateSquareMatrix(size): + return [[rnd.randint(0, 100) for i in range(size)] for j in range(size)] + +def printMatrix(matrix): + for row in matrix: + print(*row, sep="\t") + + +# Перемножение без использования потоков +def matrixMultiplyStandard(matrix1, matrix2): + l1 = len(matrix1) + l2 = len(matrix2) + global result_matrix + result = result_matrix + for i in range(l1): + for j in range(l2): + for k in range(l2): + result[i][j] += matrix1[i][k] * matrix2[k][j] + + return result + +result_matrix = [[0 for i in range(500)] for j in range(500)] + +# Перемножение в отдельном потоке +def matrixMultiplySingleThread(args): + matrix1, matrix2, start_i, end_i = args + global result_matrix + + result = result_matrix + + for i in range(start_i, end_i): + for j in range(len(matrix2[0])): + for k in range(len(matrix2)): + result[i][j] += matrix1[i - start_i][k] * matrix2[k][j] + +# Параллельное перемножение, использует ф-ю выше для каждого потока +def matrixMultiplyWithThreads(matrix1, matrix2, thread_count): + l1 = len(matrix1) + l2 = len(matrix2) + + # Кол-во строк на последний поток, если деление по потокам будет неточным + last_rows_count = 0 + + if l1 % thread_count == 0: + rows_per_thread = l1 // thread_count + else: + rows_per_thread = l1 // thread_count + last_rows_count = l1 % thread_count + + for i in range(thread_count): + start_i = i * rows_per_thread + + if (i - 1) == thread_count and last_rows_count > 0: + end_i = start_i + last_rows_count + else: + end_i = start_i + rows_per_thread + + args = [] + args.append((matrix1[start_i:end_i], matrix2, start_i, end_i)) + with Pool(processes = thread_count) as pool: + pool.map(matrixMultiplySingleThread, args) + + +if __name__ == "__main__": + + sizes = [100, 300, 500] + num_threads = [1, 5, 8, 12] + + for size in sizes: + matrix1 = generateSquareMatrix(size) + matrix2 = generateSquareMatrix(size) + start_time = time.time() + matrixMultiplyStandard(matrix1, matrix2) + end_time = time.time() + print(f"Standard size {size}: {end_time - start_time}s") + + for threads in num_threads: + start_time = time.time() + matrixMultiplyWithThreads(matrix1, matrix2, threads) + end_time = time.time() + print(f"Parallel size {size}, {threads} thread(s): {end_time - start_time}s") + + print("-" * 100) \ No newline at end of file diff --git a/bogdanov_dmitry_lab_5/README.md b/bogdanov_dmitry_lab_5/README.md new file mode 100644 index 0000000..2258f5a --- /dev/null +++ b/bogdanov_dmitry_lab_5/README.md @@ -0,0 +1,18 @@ +# Богданов Дмитрий ПИбд-42 +# Лабораторная работа №5 + + +## Функционал: + - Были созданы методы генерации и отображения матриц заданного размера + - Былы созданы методы для параллельного умножения матриц с использованием Pool + - Был написан код для бенчмаркинга стандартного и параллельного перемножений + +## Результаты выполнения: + +![изображение 1](./images/Screenshot_1.png) + +### Вывод: +Использование нескольких потоков приносит значительный выигрыш только на крупных матрицах, в то время как на матрицах меньшего размера больше времени уходит на менеджмент потоков. Это особенно заметно при сравнении результатов выполнения вычислений на матрице размером 100х100. + + +## [Видео](https://drive.google.com/file/d/1iPfLjzLiWwmszPH_KJ40vFCX-iWDLm1S/view?usp=sharing) \ No newline at end of file diff --git a/bogdanov_dmitry_lab_5/images/Screenshot_1.png b/bogdanov_dmitry_lab_5/images/Screenshot_1.png new file mode 100644 index 0000000..d0f6c98 Binary files /dev/null and b/bogdanov_dmitry_lab_5/images/Screenshot_1.png differ diff --git a/borschevskaya_anna_lab_7/README.md b/borschevskaya_anna_lab_7/README.md new file mode 100644 index 0000000..5df6529 --- /dev/null +++ b/borschevskaya_anna_lab_7/README.md @@ -0,0 +1,37 @@ +# Отчет. Лабораторная работа 7 + +## Балансировка нагрузки в распределённых системах при помощи открытых технологий на примерах + +### Какие алгоритмы и методы используются для балансировки нагрузки? +В распределенных системах балансировка нагрузки может осуществляться на разных уровнях: +- балансировка нагрузки на сетевом уровне +- балансировка нагрузки на транспортном уровне +- балансировка нагрузки на прикладном уровне + +На сетевом уровне балансировка может реализовываться с помощью таких алгоритмов, как Round Robin, Weighted Round Robin или Least Connections. +Алгоритм Round Robin основывается на принципе выделения одному доменному имени несколько IP, которые выбираются +при поступлении запроса по очереди. + +Weighted Round Robin - усовершенствованный алгоритм Round Robin, который подразумевает указание весов каждому серверу +в зависимости от доступных мощностей. + +Алгоритм Least Connections вносит в предыдущий алгоритм еще одно условие выбора сервера - количество активных подключений к нему, +избегая перегруженности имеющихся узлов. + +### Какие открытые технологии существуют для балансировки нагрузки? +Среди самых популярных открытых технологий можно выделить Nginx и Kubernetes. Nginx позволяет управлять нагрузкой на +компоненты системы с помощью различных алгоритмов и перенаправляет запросы от клиента к сервисам, выстпая в качестве реверс-прокси. +Kubernetes представляет собой платформу для управления контейнерами, которая включает встроенные механизмы для балансировки +нагрузки между подами. +### Как осуществляется балансировка нагрузки на базах данных? + +Можно уменьшить нагрузку на базу данных путем использования механизма кэширования на уровне приложения +или с помощью нереляционных БД (Redis и др.). Или с помощью шардирования данных, размещенных в базе. + +Для балансировки нагрузки на базах данных на прикладном уровне, например, существует утилита pgpool — +прокси между клиентом и сервером СУБД PostgreSQL, с помощью которого задаются правила перенаправления +запросов к БД в зависимости от их содержания (чтение/запись). +### Реверс-прокси как один из элементов балансировки нагрузки. +Реверс-прокси перенаправляет входящие запросы на соотвествующие сервисы, может выступать при этом и в качестве балансировщика нагрузки, реализуя один из ранее озвученных алгоритмов. +Как уже было сказано, примером такого компонента РС может выступать Nginx, в котором с помощью настройки конфигурационного файла можно указать как настройки проксирования, +так и добавить логику балансировки. \ No newline at end of file diff --git a/borschevskaya_anna_lab_8/README.md b/borschevskaya_anna_lab_8/README.md new file mode 100644 index 0000000..581feba --- /dev/null +++ b/borschevskaya_anna_lab_8/README.md @@ -0,0 +1,30 @@ +# Отчет. Лабораторная работа 8 + +### Популярность распределенных систем (РС) +Распределенные системы обладают рядом преимуществ, которые побуждают разработчиков адаптировать уже существующие решения к такой архитектуре (и переписывать монолит на микросервисы). +Данный подход позволяет сделать систему более отказоустойчивой, так как её компоненты становятся независимыми друг от друга. +Особенно это важно для сложных систем, для которых появляется возможность масштабировать отдельные узлы РС. +Также при разработке распределенных систем удобно распределяются задачи между командами разработки и есть возможность +использовать свой стек технологий для каждого сервиса. + +### Системы оркестрации +Системы оркестрации автоматизируют развертывание, масштабирование и управление контейнерами, что значительно упрощает +разработку и сопровождение. Однако вместе с тем они накладывают определенные требования к участникам команды разработки, +которым необходимо иметь хотя бы базовые знания об используемой технологии. + +### Очереди сообщений +Очереди обработки сообщений позволяют организовать асинхронное взаимодействие между компонентами системы. +Такой подход важен, если процесс при отправке сообщения не должен блокироваться, а ответ необязательно должен быть +получен и обработан мгновенно. Сообщения, которые передаются по очередям, могут быть некоторыми событиями или командами, +на которые могут отреагировать сразу несколько сервисов, подписанных на очередь. + +### Преимущества и недостатки РС +К преимуществам РС, как уже было сказано выше, можно отнести масштабируемость, отказоустойчивость, гибкость внедрения новых функциональностей, +а к недостаткам - сложности отладки возникающих проблем и тестирования, +возникающие сетевые задержки при прохождении запроса через несколько сервисов. + +### Параллелизм: за и против +Параллельные вычисления нужно применять там, где это действительно нужно. Например, при обработке больших данных, при возможности +разбиения задачи на несколько независимых подзадач. +Однако в случаях, где важна последовательность операций, +параллелизм может привести к усложнению логики приложения и ошибкам, а при малом объеме данных для обработки параллелизм может только ухудшить производительность. \ No newline at end of file diff --git a/dozorova_alena_lab_6/.gitignore b/dozorova_alena_lab_6/.gitignore new file mode 100644 index 0000000..0e58087 --- /dev/null +++ b/dozorova_alena_lab_6/.gitignore @@ -0,0 +1,12 @@ + +/dozorova_alena_lab_2/.vs +/dozorova_alena_lab_2/ConsoleApp1/.vs +/dozorova_alena_lab_2/ConsoleApp1/bin +/dozorova_alena_lab_2/ConsoleApp1/obj +/dozorova_alena_lab_2/ConsoleApp1/Properties/PublishProfiles +/dozorova_alena_lab_2/ConsoleApp2/.vs +/dozorova_alena_lab_2/ConsoleApp2/bin +/dozorova_alena_lab_2/ConsoleApp2/obj +/dozorova_alena_lab_6/ConsoleApp1/.vs +/dozorova_alena_lab_6/ConsoleApp1/bin +/dozorova_alena_lab_6/ConsoleApp1/obj diff --git a/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.csproj b/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.sln b/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.sln new file mode 100644 index 0000000..5701d5a --- /dev/null +++ b/dozorova_alena_lab_6/ConsoleApp1/ConsoleApp1.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35004.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1.csproj", "{29269567-7466-4C99-BEEF-F5766BDDFB24}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {29269567-7466-4C99-BEEF-F5766BDDFB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29269567-7466-4C99-BEEF-F5766BDDFB24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29269567-7466-4C99-BEEF-F5766BDDFB24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29269567-7466-4C99-BEEF-F5766BDDFB24}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EDED6E1D-0A86-43F9-94EA-6ADCC1FA1B42} + EndGlobalSection +EndGlobal diff --git a/dozorova_alena_lab_6/ConsoleApp1/Extention.cs b/dozorova_alena_lab_6/ConsoleApp1/Extention.cs new file mode 100644 index 0000000..86e8b29 --- /dev/null +++ b/dozorova_alena_lab_6/ConsoleApp1/Extention.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace ConsoleApp1 +{ + public static class Extention + { + public static int[,] CreateMatrixWithoutColumn(this int[,] matrix, int column) + { + var result = new int[matrix.GetLength(0), matrix.GetLength(1) - 1]; + for (int i = 0; i < matrix.GetLength(0); i++) + { + for (int j = 0; j < matrix.GetLength(1) - 1; j++) + { + result[i, j] = j < column ? matrix[i, j] : matrix[i, j + 1]; + } + } + return result; + } + + public static int[,] CreateMatrixWithoutRow(this int[,] matrix, int row) + { + var result = new int[matrix.GetLength(0) - 1, matrix.GetLength(1)]; + for (int i = 0; i < matrix.GetLength(0) - 1; i++) + { + for (int j = 0; j < matrix.GetLength(1); j++) + { + result[i, j] = i < row ? matrix[i, j] : matrix[i + 1, j]; + } + } + + return result; + } + + public static double CalculateDeterminant(this int[,] matrix) + { + if (matrix.GetLength(0) == 2) + { + return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0]; + } + double result = 0; + for (var j = 0; j < matrix.GetLength(0); j++) + { + result += (j % 2 == 1 ? 1 : -1) * matrix[1, j] * + matrix.CreateMatrixWithoutColumn(j).CreateMatrixWithoutRow(1).CalculateDeterminant(); + } + //Console.WriteLine("Ко мне пришли с размером " + matrix.GetLength(0)); + return result; + } + } +} diff --git a/dozorova_alena_lab_6/ConsoleApp1/Program.cs b/dozorova_alena_lab_6/ConsoleApp1/Program.cs new file mode 100644 index 0000000..b64687b --- /dev/null +++ b/dozorova_alena_lab_6/ConsoleApp1/Program.cs @@ -0,0 +1,87 @@ + +using ConsoleApp1; +using System.Data.Common; +using System.Diagnostics; +internal class Program +{ + private static void Main(string[] args) + { + var value = new int[3] {100, 300, 500 }; + + foreach(var i in value) + { + var a = CreateMatrix(i, i); + var b = CreateMatrix(i, i); + + List times = new() {}; + Console.WriteLine("Для пяти потоков: "); + for (int j = 1; j <= 5; j++) + { + var sw = new Stopwatch(); + sw.Start(); + + Calculate(a, j); + + sw.Stop(); + times.Add(sw.ElapsedTicks); + } + Console.WriteLine("Количество тиков для вычисления матрицы стороной "+i+": "+string.Join("\t", times)); + + Console.WriteLine("Для десяти потоков: "); + for (int j = 1; j <= 10; j++) + { + var sw = new Stopwatch(); + sw.Start(); + + Calculate(a, j); + + sw.Stop(); + times.Add(sw.ElapsedTicks); + } + Console.WriteLine("Количество тиков для вычисления матрицы стороной " + i + ": " + string.Join("\t", times)); + + } + } + + private static int[,] CreateMatrix(int x, int y) + { + var rnd = new Random(); + + var res = new int[y, x]; + + for (int i = 0; i < y; i++) + { + for (int j = 0; j < x; j++) + { + res[i, j] = rnd.Next(0, 100); + } + } + return res; + } + + private static double Calculate(int[,] matrix, int maxTask) + { + double res = 0; + + var semaphore = new SemaphoreSlim(maxTask, maxTask); + + for (var j = 0; j < matrix.GetLength(0) - 1; j++) + { + _ = Task.Run(() => + { + try + { + semaphore.Wait(); + res += (j % 2 == 1 ? 1 : -1) * matrix[1, j] * + matrix.CreateMatrixWithoutColumn(j). + CreateMatrixWithoutRow(1).CalculateDeterminant(); + } + finally { semaphore.Release(); } + }); + + } + + semaphore.Wait(maxTask); + return res; + } +} \ No newline at end of file diff --git a/dozorova_alena_lab_6/README.md b/dozorova_alena_lab_6/README.md new file mode 100644 index 0000000..c72aff4 --- /dev/null +++ b/dozorova_alena_lab_6/README.md @@ -0,0 +1,18 @@ +# Лабораторная работа 6 +В рамках данной работы мы изучаем выигрыш при распаралелливании процесса вычисления определителя матрицы +## Описание +Для вычисления определителя мы используем следующую формулу: +![alt text](image.png) +где ![alt text](image-1.png) - определитель матрицы, полученной из исходной вырезанием 1 строки и j столбца. + +## Запуск +По опыту прошлой лабораторной работы, в консольном приложении был реализован алгоритм вычисление детерминанта и запущено сравнение затраченного времени (в тиках) для 5 и 10 потоков. +## Результаты +Результаты: +
+![Результат](image-2.png) +
+Как мы видим, подтверждаются выводы прошлой лабораторной работы: для небольших матриц выигрыш несущественнен из-за затраты времени на работу с потоком, а для больших эта разница в скорости уже существенна + +## Видеодемонстрация +Видеодемонстрация по [адресу](https://drive.google.com/file/d/1dOMaRcTRiPwhn2E4ok1WUOeh_dD9NyDQ/view?usp=sharing) diff --git a/dozorova_alena_lab_6/image-1.png b/dozorova_alena_lab_6/image-1.png new file mode 100644 index 0000000..64f1452 Binary files /dev/null and b/dozorova_alena_lab_6/image-1.png differ diff --git a/dozorova_alena_lab_6/image-2.png b/dozorova_alena_lab_6/image-2.png new file mode 100644 index 0000000..4593b4a Binary files /dev/null and b/dozorova_alena_lab_6/image-2.png differ diff --git a/dozorova_alena_lab_6/image.png b/dozorova_alena_lab_6/image.png new file mode 100644 index 0000000..65f78f3 Binary files /dev/null and b/dozorova_alena_lab_6/image.png differ diff --git a/dozorova_alena_lab_7/readme.md b/dozorova_alena_lab_7/readme.md new file mode 100644 index 0000000..b64da16 --- /dev/null +++ b/dozorova_alena_lab_7/readme.md @@ -0,0 +1,17 @@ +**Балансировка нагрузки** предполагает равномерную нагрузку вычислительных узлов (процессора многопроцессорной ЭВМ или компьютера в сети) + +Следует различать _статическую_ и _динамическую_ балансировки, где первая выполняется до начала выполнения распределенного приложения, а вторая – в процессе. +Приведем примеры алгоритмов балансировки: +* *Круговой алгоритм*: - распределение входящих запросов между несколькими серверами в порядке циклической очередности. Модификации: + - *Взвешенный циклический перебор*, учитывающий мощность серверов + - *Динамический круговой алгоритм*, который учитывает текущую нагрузку на серверы при распределении запросов. +* *Наименьшее количество соединений* - направление входящих запросов на сервер с наименьшим количеством активных соединений в данный момент времени. Модификации: + - *Взвешенное наименьшее количество соединений* – направляет запросы на сервер с наименьшим соотношением активных соединений к его назначенному весу. +* *Наименьшее время отклика* - направление запросов на сервер, который демонстрируют наилучшую производительность в данный момент. Он учитывает два ключевых фактора: время отклика сервера и количество активных соединений. +* *Наименьший объем трафика* – динамический алгоритм балансировки нагрузки, который направляет входящие запросы на сервер, передающий наименьший объем данных в текущий момент. + +Существует достаточно много различных технологий как для программной, так и аппаратной балансировки. Наиболее популярные решения – это Nginx и OpenELB, MetalLB для Kubernetes. + +Для обеспечения балансировка нагрузки на базах данных используется механизм **репликации**. Балансировка нагрузки заключается в распределении запросов от пользователей по разным копиям (репликам) базы данных. + +**Реверс-прокси** — это сервер, который находится перед веб-серверами и пересылает запросы от клиента на эти веб-серверы. Он не является в полной мере балансировщиком, но может выполнять его функцию при большой нагрузке на систему. diff --git a/dozorova_alena_lab_8/readme.md b/dozorova_alena_lab_8/readme.md new file mode 100644 index 0000000..2a5142a --- /dev/null +++ b/dozorova_alena_lab_8/readme.md @@ -0,0 +1,12 @@ +Распределенные системы все больше набирают популярность в наше время. Этому способствуют такие ее качества как: +* *Устойчивость и масштабируемость* – возможность репликации позволяет поддерживать в работоспособном состоянии всю систему при отказе одного из ее компонентов +* *Принцип единой ответственности* – реализация каждого элемента системы в виде сервиса, ответственного за что-то одно, упрощает поддержку и дальнейшее развитие системы. +* *Увеличение производительности* – использование одновременно несколько распределенных сервисов позволяет повысить скорость обработки данных + +**Оркестраторы** призваны обеспечивать мониторинг за состоянием системы и выполнять функции по ее оптимизации: организация быстрого развертывания, балансировка нагрузки. Оркестраторы так же позволяют уведомлять пользователей о возникших проблемах и выполнять сбор, агрегацию и анализ логов. Подобная обработка данных позволяет выявить узкие места системы. Но оркестратор так же требует ресурсы на собственную работу. + +Под **сообщениями** подразумеваются данные, которыми обмениваются сервисы внутри системы. **Очереди сообщений** обеспечивают асинхронный обмен информацией. Сервис, отправляющий сообщение, взаимодействует не с другим сервисом, а с очередью и ждет ответа, не блокируя собственные процессы. Брокеры сообщений повышают отказоустойчивость такого обмена – они гарантируют доставку сообщения до сервиса-приемника. + +На мой взгляд основными *преимуществами* распределенных приложений являются их масштабируемость и отказоустойчивость. Но в то же время они имеют и достаточно весомые *недостатки* – сложность их поддержки и реализации, а также сложность обработки и трассировки транзакций. + +**Параллельные вычисления** в подобных системах следует внедрять только в том случае, когда *выигрыш от скорости вычислений значительно повышает затраты на выделение ресурсов*. Вычислить математические характеристики матрицы, к примеру, может быть оправдано, а вот разнесение высокоуровневой логики может быть неоправданно diff --git a/emelyanov_artem_lab_6/Benchmark.java b/emelyanov_artem_lab_6/Benchmark.java new file mode 100644 index 0000000..1c038e5 --- /dev/null +++ b/emelyanov_artem_lab_6/Benchmark.java @@ -0,0 +1,27 @@ +import java.util.concurrent.ExecutionException; + +public class Benchmark { + public static void main(String[] args) throws ExecutionException, InterruptedException { + int[] sizes = {5, 7, 10}; + + for (int size : sizes) { + int[][] matrix = MatrixGenerator.generateMatrix(size); + + // Последовательное вычисление + long startSequential = System.nanoTime(); + double detSequential = DeterminantCalculator.calculateDeterminant(matrix, 1); + long endSequential = System.nanoTime(); + System.out.println("Последовательно (" + size + "x" + size + "): " + (endSequential - startSequential) / 1_000_000 + " ms, детерминант: " + detSequential); + + // Параллельное вычисление + for (int numThreads : new int[]{2, 4, 8}) { + long startParallel = System.nanoTime(); + double detParallel = DeterminantCalculator.calculateDeterminant(matrix, numThreads); + long endParallel = System.nanoTime(); + System.out.println("Параллельно (" + size + "x" + size + ", " + numThreads + " потоков): " + + (endParallel - startParallel) / 1_000_000 + " ms, детерминант: " + detParallel); + } + System.out.println("--------------------------------------------------"); + } + } +} diff --git a/emelyanov_artem_lab_6/DeterminantCalculator.java b/emelyanov_artem_lab_6/DeterminantCalculator.java new file mode 100644 index 0000000..1c41c38 --- /dev/null +++ b/emelyanov_artem_lab_6/DeterminantCalculator.java @@ -0,0 +1,80 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class DeterminantCalculator { + public static int calculateDeterminant(int[][] matrix, int numThreads) throws InterruptedException, ExecutionException { + int size = matrix.length; + + // Если размер матрицы 1x1, возвращаем единственный элемент. + if (size == 1) { + return matrix[0][0]; + } + + // Если количество потоков равно 1, выполняем последовательный алгоритм. + if (numThreads == 1) { + return sequentialDeterminant(matrix); + } + + // Иначе выполняем параллельный алгоритм. + return parallelDeterminant(matrix, numThreads); + } + + private static int sequentialDeterminant(int[][] matrix) { + int size = matrix.length; + if (size == 1) { + return matrix[0][0]; + } + if (size == 2) { + return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; + } + + int determinant = 0; + for (int col = 0; col < size; col++) { + determinant += (int) (Math.pow(-1, col) * matrix[0][col] * sequentialDeterminant(getMinor(matrix, 0, col))); + } + return determinant; + } + + private static int parallelDeterminant(int[][] matrix, int numThreads) throws InterruptedException, ExecutionException { + int size = matrix.length; + ExecutorService executor = Executors.newFixedThreadPool(numThreads); + List> futures = new ArrayList<>(); + + for (int col = 0; col < size; col++) { + int finalCol = col; + futures.add(executor.submit(() -> { + double minorDet = sequentialDeterminant(getMinor(matrix, 0, finalCol)); + return Math.pow(-1, finalCol) * matrix[0][finalCol] * minorDet; + })); + } + + int determinant = 0; + for (Future future : futures) { + determinant += future.get(); + } + + executor.shutdown(); + return determinant; + } + + private static int[][] getMinor(int[][] matrix, int row, int col) { + int size = matrix.length; + int[][] minor = new int[size - 1][size - 1]; + + for (int i = 0, mi = 0; i < size; i++) { + if (i == row) continue; + for (int j = 0, mj = 0; j < size; j++) { + if (j == col) continue; + minor[mi][mj] = matrix[i][j]; + mj++; + } + mi++; + } + return minor; + } +} + diff --git a/emelyanov_artem_lab_6/MatrixGenerator.java b/emelyanov_artem_lab_6/MatrixGenerator.java new file mode 100644 index 0000000..3baecd7 --- /dev/null +++ b/emelyanov_artem_lab_6/MatrixGenerator.java @@ -0,0 +1,11 @@ +public class MatrixGenerator { + public static int[][] generateMatrix(int size) { + int[][] matrix = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + matrix[i][j] = (int) (Math.random() * 100); + } + } + return matrix; + } +} diff --git a/emelyanov_artem_lab_6/Readme.md b/emelyanov_artem_lab_6/Readme.md new file mode 100644 index 0000000..162d74e --- /dev/null +++ b/emelyanov_artem_lab_6/Readme.md @@ -0,0 +1,12 @@ +# Поиск детерминанта + +Данная работа посвящена реализации и сравнению последовательного и параллельного алгоритмов поиска детерминанта матриц на языке Java. Целью является оценка производительности при использовании разного числа потоков. + +## Результаты: + +![img.png](images/img.png) + +Как видим, однозначно сказать нельзя, для маленьких матриц многопоточность особо не повлияла. Начиная с матрицы размерностью 10, есть прибавка в производительности. Посмотрим на сложность алгоритма, и она будет что-то около O(n!), так как алгоритм рекурсивный. +Для больших матриц, типа 100 на 100, сложность будет огромной, и не думаю что такое получится посчитать. + +Ссылка на видео: https://drive.google.com/file/d/1eCNcSLLLfWGlOk5Z0y0CfOfkbxeASrdE/view?usp=sharing \ No newline at end of file diff --git a/emelyanov_artem_lab_6/images/img.png b/emelyanov_artem_lab_6/images/img.png new file mode 100644 index 0000000..52abf13 Binary files /dev/null and b/emelyanov_artem_lab_6/images/img.png differ diff --git a/emelyanov_artem_lab_6/img.png b/emelyanov_artem_lab_6/img.png new file mode 100644 index 0000000..52abf13 Binary files /dev/null and b/emelyanov_artem_lab_6/img.png differ diff --git a/emelyanov_artem_lab_7/.idea/workspace.xml b/emelyanov_artem_lab_7/.idea/workspace.xml new file mode 100644 index 0000000..b8c6381 --- /dev/null +++ b/emelyanov_artem_lab_7/.idea/workspace.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 1729344698203 + + + + + + + + + + \ No newline at end of file diff --git a/emelyanov_artem_lab_7/Readme.md b/emelyanov_artem_lab_7/Readme.md new file mode 100644 index 0000000..e74dc5c --- /dev/null +++ b/emelyanov_artem_lab_7/Readme.md @@ -0,0 +1,24 @@ +# Балансировка нагрузки в распределённых системах + +>Балансировка нагрузки - распределение сетевых или вычислительных нагрузок между несколькими серверами или ресурсами для оптимизации производительности, надежности и времени отклика. + +Существуют такие **алгоритмы** для балансировки нагрузки, как: + +- **Round Robin** — запросы идут по очереди на серверы. +- **Least Connections** — запрос направляется на сервер с наименьшей загрузкой. +- **Weighted Round Robin** — учитывает мощность серверов. + +Ну и одними из популярных **технологий**, являются: + +- **NGINX** и **HAProxy** — балансировщики на уровне HTTP/TCP. +- **Kubernetes Ingress** — управляет балансировкой в контейнерных средах. + +Также можно осуществить балансировку нагрузки на **базах данных**, с помощью: + +- **Чтение/Запись с репликами** — чтение с реплик, запись в мастер. +- **Шардинг** — деление данных по узлам. +- **PgBouncer** — управление пулами соединений. + +Для балансировки нагрузки также можно использовать **реверс-прокси**. + +>Реверс-прокси - это сервер, который принимает клиентские запросы и перенаправляет их на соответствующие внутренние сервера. Также он может быть использован для балансировки, кэширования и безопасности. \ No newline at end of file diff --git a/emelyanov_artem_lab_8/Readme.md b/emelyanov_artem_lab_8/Readme.md new file mode 100644 index 0000000..276a1d3 --- /dev/null +++ b/emelyanov_artem_lab_8/Readme.md @@ -0,0 +1,33 @@ +# Устройство распределенных систем + +> Сложные системы такие как "ВКонтакте" пишутся в **распределенном** стиле, так как это даёт такие преимущества, как: + +- **Масштабируемость**: Разделение на микросервисы позволяет масштабировать только те части системы, которые испытывают высокую нагрузку, не затрагивая другие компоненты. +- **Упрощение разработки и поддержки**: Микросервисная архитектура позволяет выделить разные команды для разработки и поддержки каждого отдельного сервиса, что ускоряет разработку и упрощает управление кодовой базой. +- **Устойчивость и отказоустойчивость**: Отказ одного микросервиса не ведет к отказу всей системы, что повышает её надежность. +- **Гибкость в выборе технологий**: Разные сервисы могут использовать разные языки программирования, базы данных и фреймворки, которые лучше подходят для конкретной задачи. + +> Но у распределённых систем можно выявить и недостатки, такие как: + +- **Сложность разработки и управления** +- **Сложность тестирования** +- **Задержки в сетевом взаимодействии** + +> Для управления контейнерами в распределенных системах, были созданы специальные системы автоматизации для управления развертыванием. Называется **орекстратор**, и его преимущества заключаются в: + +- **Автоматическое масштабирование** +- **Управление отказами** +- **Облегчение развертывания и обновления** +- **Управление конфигурациями и секретами** + +> Для асинхронного взаимодействия между сервисами придуманы **очереди сообщений**, такие как, RabbitMQ или Kafka: + +- **Сообщения** — это единицы данных, которые сервисы обмениваются друг с другом. + +**Очереди** обеспечивают: + +- **Буферизацию нагрузки** +- **Асинхронность** +- **Устойчивость к сбоям** + +> Для внедрения параллельных вычислений в распределенную систему, должны быть весомы поводы, такие как, обработка большого кол-ва данных. Но если задачи простые или важна скорость обмена между сервисами, это может быть уже не так полезно. diff --git a/kadyrov_aydar_lab_1/Image_1.png b/kadyrov_aydar_lab_1/Image_1.png new file mode 100644 index 0000000..8725f2e Binary files /dev/null and b/kadyrov_aydar_lab_1/Image_1.png differ diff --git a/kadyrov_aydar_lab_1/Image_2.png b/kadyrov_aydar_lab_1/Image_2.png new file mode 100644 index 0000000..0d1e3d9 Binary files /dev/null and b/kadyrov_aydar_lab_1/Image_2.png differ diff --git a/kadyrov_aydar_lab_1/Image_3.png b/kadyrov_aydar_lab_1/Image_3.png new file mode 100644 index 0000000..e075b91 Binary files /dev/null and b/kadyrov_aydar_lab_1/Image_3.png differ diff --git a/kadyrov_aydar_lab_1/Image_4_Work.png b/kadyrov_aydar_lab_1/Image_4_Work.png new file mode 100644 index 0000000..e349eb3 Binary files /dev/null and b/kadyrov_aydar_lab_1/Image_4_Work.png differ diff --git a/kadyrov_aydar_lab_1/README.md b/kadyrov_aydar_lab_1/README.md new file mode 100644 index 0000000..249e8a3 --- /dev/null +++ b/kadyrov_aydar_lab_1/README.md @@ -0,0 +1,173 @@ +# Лабораторная работа №1 - Знакомство с docker и docker-compose + +**Цель**: изучение современных технологий контейнеризации. + +**Задачи**: + +1. Установить средство контейнеризации docker. +2. Изучить применение и принципы docker. +3. Изучить утилиту docker-compose и структуру файла docker-compose.yml. +4. Развернуть не менее 3х различных сервисов при помощи docker-compose. +5. Оформить отчёт в формате Markdown и создать Pull Request в git-репозитории. + +## Разворачивание сервисов + +Предлагается развернуть не менее 3х сервисов через docker-compose из списка ниже: + +1. **mediawiki** + Движок вики. +2. **redmine** + Система учёта багов, т.е. баг-трекер. +3. **wordpress** + Популярная система управления контентом. +4. **drupal** + Ещё одна популярная система управления контентом. +5. **moodle** + Система для обучения, на которой построена . +6. **gitea** + Сервис для хранения репозиториев git, на котором работает этот репозиторий. + +Требования и docker-compose: + +* Несколько контейнеров. +* Хотя бы один volume. +* Хотя бы один порт, проброшенный на хост. + +При этом разворачивание системы должно пройти до конца. +Например, должен быть создан администратор и система должна корректно функционировать. +Это необходимо будет предоставить в отчёте, поэтому не забывайте делать скриншоты. + +## Ход работы + +1. Установил Docker dekstop на свою ОС (Windows) +2. Открыл терминал и с помощью команды "docker --version" проверил корректность установки +3. Запустил первый тестовый контейнер с помощью команды "docker run hello-world". (Скрин Image_1) +4. Попробовал несколько базовых команд.(Скрин Image_2) +5. C помощью команды "docker-compose --version" проверил версию Docker-Compose. (Скрин Image_3) +6. Развернул сервисы (Описал ниже) + +## Объяснение работы кода: + +## WordPress: + +1. Эта строка отвечает за образ сборки: + +image: wordpress:latest + +Используем последний официальный образ WordPress. + +2. Задание имени контейнера: + +container_name: wordpress + +Устанавливается имя контейнера как wordpress. + +3. Проброс портов: + +Порт 80 контейнера пробрасывается на порт 8080 хоста. + +4. Тома для хранения данных: + +volumes: + - wordpress_data:/var/www/html + +Том wordpress_data монтируется в директорию /var/www/html контейнера для хранения данных WordPress. + +5. Переменные окружения для WordPress: + +environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_USER: example_user + WORDPRESS_DB_PASSWORD: example_password + WORDPRESS_DB_NAME: example_db + +Здесь задаются параметры для подключения к базе данных: + +WORDPRESS_DB_HOST: адрес базы данных (контейнер с именем db). +WORDPRESS_DB_USER: имя пользователя базы данных. +WORDPRESS_DB_PASSWORD: пароль пользователя базы данных. +WORDPRESS_DB_NAME: имя базы данных. + +6. Зависимость от базы данных: + +depends_on: db + +Указываем, что WordPress зависит от контейнера с базой данных (db), который должен запуститься первым. + +## Redmine: + +1. Эта строка отвечает за образ сборки: + +image: redmine:latest + +Используем последний официальный образ Redmine. + +2. Задание имени контейнера: + +container_name: redmine + +Устанавливается имя контейнера как redmine. + +3. Проброс портов: + +ports:"8081:3000" + +Порт 3000 контейнера пробрасывается на порт 8081 хоста + +4. Переменные окружения для Redmine: + +environment: + REDMINE_DB_MYSQL: redmine_db + REDMINE_DB_USERNAME: redmine_user + REDMINE_DB_PASSWORD: redmine_password + +Задаются параметры для подключения к базе данных: + +REDMINE_DB_MYSQL: имя контейнера базы данных. +REDMINE_DB_USERNAME: имя пользователя базы данных. +REDMINE_DB_PASSWORD: пароль пользователя базы данных. + +5. Зависимость от базы данных: + + +depends_on: + - redmine_db + +Redmine зависит от контейнера с базой данных redmine_db. + +## Gitea: + +1. Эта строка отвечает за образ сборки: + +image: gitea/gitea:latest + +Используем последний официальный образ Gitea. + +2. Задание имени контейнера: + +container_name: gitea + +Устанавливается имя контейнера как gitea. + +3. Проброс портов: + +ports:"8082:3000" + +Порт 3000 контейнера пробрасывается на порт 8082 хоста + +4. Тома для хранения данных: + +volumes: + - gitea_data:/data + +Том gitea_data монтируется в директорию /data контейнера для хранения данных Gitea. + +5. Переменные окружения для Gitea: + +environment: + - USER_UID=1000 + - USER_GID=1000 + +## Видео по ссылку: + +https://vk.com/video64471408_456239204?list=ln-0pkqwQsSiTkihNDILH \ No newline at end of file diff --git a/kadyrov_aydar_lab_1/docker-compose.yml b/kadyrov_aydar_lab_1/docker-compose.yml new file mode 100644 index 0000000..932b043 --- /dev/null +++ b/kadyrov_aydar_lab_1/docker-compose.yml @@ -0,0 +1,68 @@ +version: '3' + +services: + wordpress: + image: wordpress:latest + container_name: wordpress + ports: + - "8080:80" + environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_USER: example_user + WORDPRESS_DB_PASSWORD: example_password + WORDPRESS_DB_NAME: example_db + volumes: + - wordpress_data:/var/www/html + depends_on: + - db + + db: + image: mysql:5.7 + container_name: wordpress_db + environment: + MYSQL_DATABASE: example_db + MYSQL_USER: example_user + MYSQL_PASSWORD: example_password + MYSQL_ROOT_PASSWORD: root_password + volumes: + - db_data:/var/lib/mysql + + redmine: + image: redmine:latest + container_name: redmine + ports: + - "8081:3000" + environment: + REDMINE_DB_MYSQL: redmine_db + REDMINE_DB_USERNAME: redmine_user + REDMINE_DB_PASSWORD: redmine_password + depends_on: + - redmine_db + + redmine_db: + image: mysql:5.7 + container_name: redmine_db + environment: + MYSQL_DATABASE: redmine + MYSQL_USER: redmine_user + MYSQL_PASSWORD: redmine_password + MYSQL_ROOT_PASSWORD: root_password + volumes: + - redmine_db_data:/var/lib/mysql + + gitea: + image: gitea/gitea:latest + container_name: gitea + ports: + - "8082:3000" + environment: + - USER_UID=1000 + - USER_GID=1000 + volumes: + - gitea_data:/data + +volumes: + wordpress_data: + db_data: + redmine_db_data: + gitea_data: diff --git a/kadyrov_aydar_lab_2/.gitignore b/kadyrov_aydar_lab_2/.gitignore new file mode 100644 index 0000000..49065ec --- /dev/null +++ b/kadyrov_aydar_lab_2/.gitignore @@ -0,0 +1,10 @@ +data/ +result/ +__pycache__/ +*.py[cod] +*.env +*.venv +.env.local +venv/ +env/ +.idea/ \ No newline at end of file diff --git a/kadyrov_aydar_lab_2/README.md b/kadyrov_aydar_lab_2/README.md new file mode 100644 index 0000000..0bd615d --- /dev/null +++ b/kadyrov_aydar_lab_2/README.md @@ -0,0 +1,78 @@ +# Лабораторная работа №2 - Разработка простейшего распределённого приложения + +## Задание + +**Цель**: Разработать два приложения, результат работы первого из которых становится входными данными для второго. + +**Задачи**: +1. Разработать два приложения: + - **app_one**: Ищет в каталоге /var/data файл с наибольшим количеством строк и копирует его содержимое в /var/result/data.txt. + - **app_two**: Ищет наименьшее число из файла /var/result/data.txt и сохраняет его в третьей степени в /var/result/result.txt. +2. Разработать файлы сборки Docker для каждого приложения. +3. Собрать файл docker-compose.yml для запуска обоих приложений. +4. Настроить монтирование директорий для обмена данными между контейнерами. +5. Правильно закоммитить решение с использованием .gitignore для исключения лишних файлов. + +## Варианты задания: + +1. **app_one**: + - Ищет файл с наибольшим количеством строк в каталоге /var/data. + - Копирует содержимое этого файла в /var/result/data.txt. + +2. **app_two**: + - Читает файл /var/result/data.txt. + - Ищет наименьшее число и сохраняет его третью степень в /var/result/result.txt. + +### Требования: +1. **Docker**: Платформа для контейнеризации приложений. +2. **Docker Compose**: Инструмент для управления многоконтейнерными приложениями на основе файла docker-compose.yml. + +### Сборка и запуск: + +В директории, где находится файл docker-compose.yml, выполним команду для сборки и запуска всех контейнеров: + + +docker-compose up --build + + +Эта команда: +1. Собирает все Docker-образы для сервисов. +2. Запускает контейнеры. +3. Автоматически подготавливает данные и выполняет приложения последовательно. + +### Результаты: + +После успешного завершения работы контейнеров можно проверить результаты в папке result: +- **data.txt** — файл, полученный после выполнения первого приложения (содержит копию файла с наибольшим количеством строк из папки data). +- **result.txt** — файл, полученный после выполнения второго приложения (содержит третью степень наименьшего числа из файла data.txt). + +## Описание работы + +### Программы: + +1. **app_one/main.py**: + - Ищет файл с наибольшим количеством строк в каталоге /var/data. + - Копирует содержимое этого файла в /var/result/data.txt. + +2. **app_two/main.py**: + - Читает файл /var/result/data.txt. + - Ищет наименьшее число в файле и возводит его в третью степень. + - Сохраняет результат в файл /var/result/result.txt. + +### Генерация данных: + +Для создания случайных данных был написан скрипт generate_data.py: +- Создает несколько файлов с целыми числами в каталоге /var/data. +- Каждый файл содержит случайные числа, которые будут использоваться первым приложением. + +### Dockerfile: + +Каждое приложение имеет собственный Dockerfile, где указаны шаги для сборки Python-образов и запуска программ. + +## Вывод + +В результате лабораторной работы было создано простейшее распределенное приложение, которое использует Docker и Docker Compose для запуска двух программ, обрабатывающих данные в контейнерах. + +## Видео ВК + +https://vk.com/video64471408_456239205?list=ln-nzLhpgninZdZBOzarw \ No newline at end of file diff --git a/kadyrov_aydar_lab_2/app_one/Dockerfile b/kadyrov_aydar_lab_2/app_one/Dockerfile new file mode 100644 index 0000000..5378828 --- /dev/null +++ b/kadyrov_aydar_lab_2/app_one/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_2/app_one/main.py b/kadyrov_aydar_lab_2/app_one/main.py new file mode 100644 index 0000000..1b2d430 --- /dev/null +++ b/kadyrov_aydar_lab_2/app_one/main.py @@ -0,0 +1,38 @@ +import os + +def get_file_with_most_lines(directory): + max_lines = 0 + target_file = "" + + for filename in os.listdir(directory): + filepath = os.path.join(directory, filename) + if os.path.isfile(filepath): + with open(filepath, 'r') as f: + line_count = sum(1 for _ in f) + if line_count > max_lines: + max_lines = line_count + target_file = filename + + return target_file + +def copy_file(src_directory, dest_directory, filename): + src_filepath = os.path.join(src_directory, filename) + dest_filepath = os.path.join(dest_directory, 'data.txt') + + os.makedirs(dest_directory, exist_ok=True) + + with open(src_filepath, 'r') as src_file: + with open(dest_filepath, 'w') as dest_file: + dest_file.write(src_file.read()) + +def main(): + src_directory = '/var/data' + dest_directory = '/var/result' + + target_file = get_file_with_most_lines(src_directory) + if target_file: + copy_file(src_directory, dest_directory, target_file) + print(f"File {target_file} copied to {dest_directory}/data.txt") + +if __name__ == "__main__": + main() diff --git a/kadyrov_aydar_lab_2/app_two/Dockerfile b/kadyrov_aydar_lab_2/app_two/Dockerfile new file mode 100644 index 0000000..5378828 --- /dev/null +++ b/kadyrov_aydar_lab_2/app_two/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_2/app_two/main.py b/kadyrov_aydar_lab_2/app_two/main.py new file mode 100644 index 0000000..4c2f88e --- /dev/null +++ b/kadyrov_aydar_lab_2/app_two/main.py @@ -0,0 +1,25 @@ +import os + +def get_largest_number_from_file(filepath): + with open(filepath, 'r') as f: + numbers = [int(line.strip()) for line in f.readlines()] + return max(numbers) + +def save_square_of_number(number, output_filepath): + result = number ** 2 + with open(output_filepath, 'w') as f: + f.write(str(result)) + +def main(): + input_filepath = '/var/result/data.txt' + output_filepath = '/var/result/result.txt' + + if os.path.exists(input_filepath): + largest_number = get_largest_number_from_file(input_filepath) + save_square_of_number(largest_number, output_filepath) + print(f"Largest number squared: {largest_number}^2 saved to {output_filepath}") + else: + print(f"Input file {input_filepath} not found!") + +if __name__ == "__main__": + main() diff --git a/kadyrov_aydar_lab_2/data_generator/Dockerfile b/kadyrov_aydar_lab_2/data_generator/Dockerfile new file mode 100644 index 0000000..b98495c --- /dev/null +++ b/kadyrov_aydar_lab_2/data_generator/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "generate_data.py"] diff --git a/kadyrov_aydar_lab_2/data_generator/generate_data.py b/kadyrov_aydar_lab_2/data_generator/generate_data.py new file mode 100644 index 0000000..e8f2db5 --- /dev/null +++ b/kadyrov_aydar_lab_2/data_generator/generate_data.py @@ -0,0 +1,29 @@ +import os +import random + + +def generate_random_files(directory, num_files, num_lines_per_file, min_value, max_value): + os.makedirs(directory, exist_ok=True) + + for i in range(num_files): + file_path = os.path.join(directory, f"file_{i + 1}.txt") + with open(file_path, 'w') as f: + for _ in range(num_lines_per_file): + random_number = random.randint(min_value, max_value) + f.write(f"{random_number}\n") + print(f"Generated file: {file_path}") + + +def main(): + data_directory = '/var/data' + num_files = 10 + num_lines_per_file = 12 + min_value = 1 + max_value = 100 + + generate_random_files(data_directory, num_files, num_lines_per_file, min_value, max_value) + print(f"Generated {num_files} files in {data_directory}") + + +if __name__ == "__main__": + main() diff --git a/kadyrov_aydar_lab_2/docker-compose.yml b/kadyrov_aydar_lab_2/docker-compose.yml new file mode 100644 index 0000000..872c5fd --- /dev/null +++ b/kadyrov_aydar_lab_2/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3' +services: + data_generator: + build: + context: ./data_generator + volumes: + - ./data:/var/data + app_one: + build: + context: ./app_one + volumes: + - ./data:/var/data + - ./result:/var/result + depends_on: + - data_generator + app_two: + build: + context: ./app_two + volumes: + - ./result:/var/result + depends_on: + - app_one diff --git a/kadyrov_aydar_lab_3/README.md b/kadyrov_aydar_lab_3/README.md new file mode 100644 index 0000000..1cbbb4f --- /dev/null +++ b/kadyrov_aydar_lab_3/README.md @@ -0,0 +1,42 @@ + +# Лабораторная работа №3 - REST API, шлюз и синхронный обмен данными между микросервисами + +## Задание + +### Цель: +Изучение принципов проектирования с использованием паттерна шлюза, организации синхронной передачи данных между микросервисами и применения архитектурного стиля RESTful API. + +### Задачи: +1. Создание двух микросервисов, которые реализуют операции CRUD для связанных сущностей. +2. Реализация механизма синхронного обмена данными между микросервисами. +3. Настройка шлюза на базе Nginx в качестве прозрачного прокси-сервера. + +### Микросервисы: +1. **hero_service** — сервис, который управляет информацией о героях. +2. **item_service** — сервис, который обрабатывает данные о предметах, принадлежащих героям. + +### Связь между микросервисами: +- Один документ (hero) может иметь множество связанных предметов (items) (соотношение 1 ко многим). + +## Как запустить проект: +Для запуска приложения необходимо выполнить команду: +```bash +docker-compose up +``` + +## Описание работы: + +Для разработки микросервисов был выбран язык программирования Python. + +### Синхронный обмен данными +Сервис `hero_service` отправляет HTTP-запросы к `item_service` при выполнении определенных операций CRUD. Это позволяет получать актуальную информацию о предметах, связанных с конкретными героями. + +### Docker Compose +Конфигурационный файл `docker-compose.yml` представляет собой многоконтейнерное приложение, которое включает в себя три сервиса: `hero_service`, `item_service` и `nginx`. Функция маршрутизации возложена на сервер Nginx, который обрабатывает запросы и перенаправляет их на соответствующие микросервисы. + +### Nginx +Конфигурационный файл Nginx определяет настройки веб-сервера и обратного прокси, который управляет входящими запросами и направляет их на соответствующие сервисы. + +### ВК ВИДЕО + +https://vk.com/video64471408_456239206?list=ln-eG1UX8zXWbZkc651DD \ No newline at end of file diff --git a/kadyrov_aydar_lab_3/docker-compose.yml b/kadyrov_aydar_lab_3/docker-compose.yml new file mode 100644 index 0000000..eaa095c --- /dev/null +++ b/kadyrov_aydar_lab_3/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.8' + +services: + hero_service: + build: + context: ./hero_service + dockerfile: Dockerfile + ports: + - "5000:5000" + + item_service: + build: + context: ./item_service + dockerfile: Dockerfile + ports: + - "5001:5001" + + nginx: + image: nginx:latest + volumes: + - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf + ports: + - "80:80" + depends_on: + - hero_service + - item_service diff --git a/kadyrov_aydar_lab_3/hero_service/Dockerfile b/kadyrov_aydar_lab_3/hero_service/Dockerfile new file mode 100644 index 0000000..7a7319a --- /dev/null +++ b/kadyrov_aydar_lab_3/hero_service/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.11 + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_3/hero_service/main.py b/kadyrov_aydar_lab_3/hero_service/main.py new file mode 100644 index 0000000..9efb650 --- /dev/null +++ b/kadyrov_aydar_lab_3/hero_service/main.py @@ -0,0 +1,51 @@ +from flask import Flask, jsonify, request +import uuid + +app = Flask(__name__) + +heroes = {} + +@app.route('/heroes', methods=['GET']) +def get_heroes(): + return jsonify(list(heroes.values())) + +@app.route('/heroes/', methods=['GET']) +def get_hero(hero_uuid): + hero = heroes.get(str(hero_uuid)) + if hero: + return jsonify(hero) + return jsonify({'error': 'Not found'}), 404 + +@app.route('/heroes', methods=['POST']) +def create_hero(): + data = request.get_json() + hero_uuid = str(uuid.uuid4()) + hero = { + 'uuid': hero_uuid, + 'name': data['name'], + 'role': data['role'], + 'strength': data['strength'] + } + heroes[hero_uuid] = hero + return jsonify(hero), 201 + +@app.route('/heroes/', methods=['PUT']) +def update_hero(hero_uuid): + hero = heroes.get(str(hero_uuid)) + if not hero: + return jsonify({'error': 'Not found'}), 404 + data = request.get_json() + hero['name'] = data['name'] + hero['role'] = data['role'] + hero['strength'] = data['strength'] + return jsonify(hero) + +@app.route('/heroes/', methods=['DELETE']) +def delete_hero(hero_uuid): + if str(hero_uuid) in heroes: + del heroes[str(hero_uuid)] + return '', 204 + return jsonify({'error': 'Not found'}), 404 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/kadyrov_aydar_lab_3/hero_service/requirements.txt b/kadyrov_aydar_lab_3/hero_service/requirements.txt new file mode 100644 index 0000000..e3e9a71 --- /dev/null +++ b/kadyrov_aydar_lab_3/hero_service/requirements.txt @@ -0,0 +1 @@ +Flask diff --git a/kadyrov_aydar_lab_3/item_service/Dockerfile b/kadyrov_aydar_lab_3/item_service/Dockerfile new file mode 100644 index 0000000..7a7319a --- /dev/null +++ b/kadyrov_aydar_lab_3/item_service/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.11 + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_3/item_service/main.py b/kadyrov_aydar_lab_3/item_service/main.py new file mode 100644 index 0000000..a1c4890 --- /dev/null +++ b/kadyrov_aydar_lab_3/item_service/main.py @@ -0,0 +1,51 @@ +from flask import Flask, jsonify, request +import uuid + +app = Flask(__name__) + +items = {} + +@app.route('/items', methods=['GET']) +def get_items(): + return jsonify(list(items.values())) + +@app.route('/items/', methods=['GET']) +def get_item(item_uuid): + item = items.get(str(item_uuid)) + if item: + return jsonify(item) + return jsonify({'error': 'Not found'}), 404 + +@app.route('/items', methods=['POST']) +def create_item(): + data = request.json + item_uuid = str(uuid.uuid4()) + item = { + 'uuid': item_uuid, + 'name': data['name'], + 'type': data['type'], + 'hero_uuid': data['hero_uuid'] + } + items[item_uuid] = item + return jsonify(item), 201 + +@app.route('/items/', methods=['PUT']) +def update_item(item_uuid): + item = items.get(str(item_uuid)) + if not item: + return jsonify({'error': 'Not found'}), 404 + data = request.json + item['name'] = data['name'] + item['type'] = data['type'] + item['hero_uuid'] = data['hero_uuid'] + return jsonify(item) + +@app.route('/items/', methods=['DELETE']) +def delete_item(item_uuid): + if str(item_uuid) in items: + del items[str(item_uuid)] + return '', 204 + return jsonify({'error': 'Not found'}), 404 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5001) diff --git a/kadyrov_aydar_lab_3/item_service/requirements.txt b/kadyrov_aydar_lab_3/item_service/requirements.txt new file mode 100644 index 0000000..e3e9a71 --- /dev/null +++ b/kadyrov_aydar_lab_3/item_service/requirements.txt @@ -0,0 +1 @@ +Flask diff --git a/kadyrov_aydar_lab_3/nginx/nginx.conf b/kadyrov_aydar_lab_3/nginx/nginx.conf new file mode 100644 index 0000000..3774360 --- /dev/null +++ b/kadyrov_aydar_lab_3/nginx/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + + location /heroes { + proxy_pass http://hero_service:5000; + } + + location /items { + proxy_pass http://item_service:5001; + } +} diff --git a/kuzarin_maxim_lab_7/README.md b/kuzarin_maxim_lab_7/README.md new file mode 100644 index 0000000..1286984 --- /dev/null +++ b/kuzarin_maxim_lab_7/README.md @@ -0,0 +1,13 @@ +# Балансировка нагрузки в распределённых системах +*Балансировка нагрузки в распределенных системах* – это метод распределения сетевого трафика по пулу ресурсов приложения. Для этого существует достаточно большое число инструментов. +## Алгоритмы балансировки +Всё множество алгоритмов для балансировки можно условно разделить на 2 большие группы: рассчитанные на сохранение состояния и не рассчитанные. +- Первые, по большому счёту, балансируют подключения пользователей. Но это никак не гарантирует равномерного распределения их запросов. +- Вторые – балансируют запросы между ресурсами. Это позволяет распределять нагрузку чуть более равномерно, но при этом необходимо задумываться о том, что бы система могла работать в режиме без сохранения состояния. + +Сами же алгоритмы, по большому счёту, отличаются только механизмом выбора экземпляра ресурса, к которому перенаправляется запрос. Это может быть равномерное распределение (алгоритм **Round Robin**) или вариации взвешенного (алгоритм **Weighted Round Robin**). +На сегодняшний день существует множество открытых технологий балансировки нагрузки. Например, всем известный **Nginx** предоставляет инструменты для настройки подобной функции. Так же есть ряд проектов, полностью заточенных под балансировку нагрузки в Kubernetes (**OpenELB**, **MetalLB**). +## Балансировка нагрузки на БД +Балансировка нагрузки на БД – более сложный и комплексный вопрос. Он предполагает, что у СУБД должен быть механизм репликации данных, или шардинга. Например, такое умеет **PostgreSQL** и **MongoDB** +## Реверс-прокси +Реверс-прокси в данном случае напрямую не является инструментом балансировки нагрузки. Скорее это инструмент, эту балансировку и распределённость в целом, скрывающий за единым фасадом. Самым известным представителем этого семейства можно назвать уже упомянутый ранее **Nginx** \ No newline at end of file diff --git a/kuzarin_maxim_lab_8/README.md b/kuzarin_maxim_lab_8/README.md new file mode 100644 index 0000000..2976887 --- /dev/null +++ b/kuzarin_maxim_lab_8/README.md @@ -0,0 +1,19 @@ +# Устройство распределенных систем +Сегодня всё больше и больше сложным систем начинают переводить, или проектировать в распределённом формате. +## Причины популярности РС +На то есть много причин, перечислим основные из них: + +- **Размеры.** На данный момент заметна тенденция создания не просто отдельных приложений для выполнения конкретных задач, а формирования некоторой экосистемы, где пользователь может делать много всего через единую точку входа. Это повышает сложность проектирования системы: она больше физически не может поместиться в голове у разработчиков. Поэтому переход на структуру, когда всё разбито на мелкие, взаимосвязанные элементы вполне оправдан. + +- **Масштабируемость.** Нагрузка на системы растёт постоянно. И нет оснований полагать, что дальше будет не так. Монолит конечно может держать нагрузку, но он лишён возможности точечного горизонтального масштабирования (упёрлись в то, что у нас очень долго работает механизм отправки сообщений о готовности – увеличили количество таких сервисов – узкое место ушло) + +- **Переиспользуемость.** Написанные один раз сервис авторизации, можно с минимальными доработками перенести и в другие продукты. Это сокращает затраты на разработку системы. + +## Оркестраторы +Так же, с приходом распределённых систем важную роль стали играть оркестраторы. Фактически, они смогли собрать в себе сразу ряд полезных функций: мониторинг состояния системы, оповещения пользователей о том, что что-то не так, организация процесса быстрого развёртывания, Возможность сбора, агрегации и анализа логов, для поиска узких мест системы и их дальнейшего устранения. Но, как и всегда, оркестратор имеет и минусы: он требует ресурсы (и порой не малые) для своей работы, порог входа у него не всегда низкий. +## Очереди сообщений +В распределённой системе, помимо прочего, появляется возможность активно использовать системы асинхронного обмена сообщениями через очереди. Этот механизм значительно экономит ресурсы процессора, так как позволяет вместо нахождения в бесконечном цикле ожидания (пока запрос обработается) делать что-то полезное. К тому же брокеры сообщений, которые часто используются в асинхронной обработке, могут повышать надёжность системы: если в момент обработки сообщения упадёт сервис-приёмник, то информация о подтверждении не доедет до очереди и сообщения будет доставлено через другой экземпляр, а не потеряется, так как очередь будет считать его недоставленным, и повторять отправку. +## Параллельные вычисления +Что же касается параллельных вычислений – это в первую очередь вопрос производительности. Использование нескольких потоков может ускорить работу кратно, но не всегда это применимо, так как порой перестройка алгоритма может потребовать ресурсов многократно больших, чем будет выигрыш, полученный от ускорения. Если речь о чистой математике(умножить матрицы) – это и правда полезно, а вот попытка развести высокоуровневую бизнес-логику по потокам – может быть изначально плохой идеей. +## Недостатки РС +Стоит так же отметить, что распределённые системы, несмотря на достоинства, имеют и недостатки. В основном их источник – отсутствие большого опыта создания таких систем, а так же простое правило, что вероятность ошибки в системе тем больше, чем из большего количества элементов она состоит. Отлаживать монолит и искать в нём уязвимости – проще, чем задумываться над тем, что будет, если в момент REST запроса один из сервисов откажет, или сеть упадёт. diff --git a/lazarev_andrey_lab_3/.gitignore b/lazarev_andrey_lab_3/.gitignore new file mode 100644 index 0000000..eba74f4 --- /dev/null +++ b/lazarev_andrey_lab_3/.gitignore @@ -0,0 +1 @@ +venv/ \ No newline at end of file diff --git a/lazarev_andrey_lab_3/README.md b/lazarev_andrey_lab_3/README.md new file mode 100644 index 0000000..0fd6a66 --- /dev/null +++ b/lazarev_andrey_lab_3/README.md @@ -0,0 +1,76 @@ +# Лабораторная работа №2 + +## Описание проекта + +Проект разворачивает 3 программы в отдельных контейнерах с использованием Docker Compose: +1. **author_service** - сервис, с CRUD операциями для авторов; +2. **publication_service** - сервис, с CRUD операциями для публикаций; +3. **nginx** - веб-сервер и прокси-сервер, является маршрутизатором. + +Между первыми двумя сервисами имеется связь один(`Автор`) ко многим(`Публикация`). + +## Струкутура проекта + +### Проект состоит из: + +- 2 папки(author_service, publication_service) + - Каждая папка содержит в себе файл с расширением `.py` с кодом программы; + - Кадлая папка сожержит в себе файл `Dockerfile` с инструкцией по созданию Docker образа. + +- Файл `.gitignore` для исключения временных файлов директории `venv/`; + +- Файл `docker-compose.yml` с конфигурацией Docker Compose; + +- Файл `nginx.conf` конфигурации для веб-сервера NGINX с параметрами работы сервера; + +- Файл `requirements.txt` с перечислением всех необходимых библиотек для запуска. + +Комментарии в файлах. + +## Запуск + +1. Скачать и установить Docker и Docker Compose; +2. Перейти в директорию с файлом docker-compose.yml; +3. Открыть консоль и запустить сервисы командой +```bash +docker-compose up --build -d +``` +4. Дождаться запуска всех сервисов +```bash + [+] Running 3/3 + ✔ Container lazarev_andrey_lab_2-generate-files-1 Started 0.5s + ✔ Container lazarev_andrey_lab_2-first-1 Started 1.3s + ✔ Container lazarev_andrey_lab_2-second-1 Started 2.0s +``` +5. Остановка всех сервисов +Для завершения работы с сервисами необходимо выполнить команду: + ```bash + docker-compose down + ``` +Дождаться завершения работы: +```bash +[+] Running 4/4 + ✔ Container lazarev_andrey_lab_2-second-1 Removed 0.0s + ✔ Container lazarev_andrey_lab_2-first-1 Removed 0.0s + ✔ Container lazarev_andrey_lab_2-generate-files-1 Removed 0.0s + ✔ Network lazarev_andrey_lab_2_default Removed 0.4s +``` + +## Cписок команд +- Author_service + - `http://localhost:8000/author_service/author` - список авторов + - `http://localhost:8000/author_service/author/{id автора}` - конкретный автор + - `http://localhost:8000/author_service/author/full/{id автора}` - автор и полный список его публикаций + - `http://localhost:8000/author_service/author?name={имя}&second_name={фамилия}&age={возраст}` - добавление нового автора + - `http://localhost:8000/author_service/author/{id автора}?name={новое имя}` - изменение имени автора + +- Publication_service + - `http://localhost:8000/publication_service/publication` - список публикаций + - `http://localhost:8000/publication_service/publication/{id публикации}` - конкретная публикация + - `http://localhost:8000/publication_service/publication/full/{id публикации}` - публикация и полная информация об авторе + - `http://localhost:8000/publication_service/publication?name={название}&public_year={год выпуска}&author_id={id автора}` - добавление новой публикации + - `http://localhost:8000/publication_service/publication/{id публикации}?name={новое название}` - изменение названия публикации +## Видеодемонстрация работоспособности + +[Демонстрация работы сервисов](https://files.ulstu.ru/s/5D2i6gbLn6r2jsA) + diff --git a/lazarev_andrey_lab_3/author_service/Dockerfile b/lazarev_andrey_lab_3/author_service/Dockerfile new file mode 100644 index 0000000..ea8f0e8 --- /dev/null +++ b/lazarev_andrey_lab_3/author_service/Dockerfile @@ -0,0 +1,17 @@ +# Использует базовый образ Python 3.9 на основе slim-версии +FROM python:3.10-slim + +# Устанавливаю рабочую директорию внутри контейнера +WORKDIR /app + +# Копирую файл requirements.txt в контейнер +COPY requirements.txt /app/ + +# Устанавливаю зависимости +RUN pip install --no-cache-dir -r requirements.txt + +#аналогично копирую +COPY author_service/main.py . + +# Задает команду для запуска контейнера +CMD ["python", "main.py"] \ No newline at end of file diff --git a/lazarev_andrey_lab_3/author_service/main.py b/lazarev_andrey_lab_3/author_service/main.py new file mode 100644 index 0000000..8107c08 --- /dev/null +++ b/lazarev_andrey_lab_3/author_service/main.py @@ -0,0 +1,110 @@ +from fastapi import FastAPI, HTTPException +from fastapi.responses import JSONResponse +from pydantic import BaseModel, Field +from uuid import UUID, uuid4 +import requests + +#Инициализация веб-приложения +app = FastAPI(title="Author service") + +#Строка подключения к публикациям +publication_url='http://publication_service:8009' + +#Сущность автор с полями имя, фамилия, возраст. +class Author(BaseModel): + uuid_: UUID = Field(default_factory=uuid4) + name: str | None + second_name: str | None + age: int | None + +#Заранее заполненный список авторов, в некоторых есть uuid они пригодятся при создании публикаций +data: list[Author] = [ + Author(uuid_="92e78b56-0026-4561-b9f6-ba628110c900", name="Андрей", second_name="Лазарев", age=21), + Author(uuid_="3203b355-d844-4d5a-ad91-a9e0135cd9d9",name="Павел", second_name="Сорокин", age=20), + Author(name="Дарья", second_name="Балберова", age=21), + Author(name="Дмитрий", second_name="Курило", age=24), + Author(name="Александр", second_name="Дырночкин", age=24) +] + +#Получить список всех авторов +@app.get("/author", tags=["Author"]) +def all_authors(): + return data + +#Получить одного автора по uuid +@app.get("/author/{author_id}", tags=["Author"]) +def get_author(author_id: UUID): + author = next((x for x in data if x.uuid_ == author_id), None) + + if not author: + return HTTPException(status_code=404, detail="Автор не найден") + + return author + +#Получить одного автора по uuid с списком его публикаций +@app.get("/author/full/{author_id}") +def get_publications_by_author(author_id: UUID): + author = get_author(author_id) + + if not author: + return HTTPException(status_code=404, detail="Автор не найден") + + publications = requests.get(f"{publication_url}/publication/author/{author_id}") + + if not publications: + return HTTPException(status_code=404, detail="Публикации не найдены") + + result = author.model_dump() + result['publications'] = publications.json() + + return result + +#Добавление нового автора, все поля обязательные +@app.post("/author", tags=["Author"]) +def add_author(name: str, second_name: str, age: int): + author = next((x for x in data if x.name == name and x.second_name == second_name and x.age == age), None) + + if author: + return HTTPException(status_code=404, detail="Такой автор уже существует") + + try: + data.append(Author(name=name, second_name=second_name, age=age)) + return JSONResponse(content={"message": "Автор успешно добавлен"}, status_code=200) + + except Exception as e: + return HTTPException(status_code=404, detail={"Автор не был добавлен с ошибкой": str(e)}) + +#Изменение автора по uuid +@app.put("/author/{author_id}", tags=["Author"]) +def update_author(author_id: UUID, name: str = None , second_name: str = None, age: int = None): + author = get_author(author_id) + if author: + index = data.index(author) + if name: + data[index].name = name + if second_name: + data[index].second_name = second_name + if age: + data[index].age = age + return JSONResponse(content={"message": "Автор успешно изменен"}, status_code=200) + + else: + return HTTPException(status_code=404, detail={"Автор не найден": {author}}) + +#Удаление автора по uuid +@app.delete("/author/{author_id}", tags=["Author"]) +def delete_author(author_id: UUID): + author = get_author(author_id) + + if author: + index = data.index(author) + del data[index] + return JSONResponse(content={"message": "Автор успешно удален"}, status_code=200) + + else: + return HTTPException(status_code=404, detail={"Автор не найден": {author}}) + +#Запуск +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8008) \ No newline at end of file diff --git a/lazarev_andrey_lab_3/docker-compose.yml b/lazarev_andrey_lab_3/docker-compose.yml new file mode 100644 index 0000000..7442dc3 --- /dev/null +++ b/lazarev_andrey_lab_3/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.8' +services: + + author_service: + build: + context: . #Контекст сборки — текущая директория (корневая папка проекта). + dockerfile: ./author_service/Dockerfile # Путь до Dockerfile для сборки контейнера. + expose: # Указывает, какой порт будет открыт внутри контейнера. + - 8008 + + publication_service: + build: + context: . + dockerfile: ./publication_service/Dockerfile + expose: + - 8009 + + nginx: # Третий сервис, называемый "nginx". + image: nginx # Используется готовый образ NGINX из Docker Hub. + ports: # Публикует порты для доступа к NGINX. + - 8000:8000 # Проброс порта: внешний порт 8000 связан с внутренним портом 8000. + volumes: # Монтирует локальные файлы/директории в контейнер. + - ./nginx.conf:/etc/nginx/nginx.conf # Локальный файл nginx.conf будет монтирован в контейнер по пути /etc/nginx/nginx.conf. + depends_on: # Зависимости. NGINX будет запускаться после запуска указанных сервисов. + - author_service # NGINX зависит от запуска author_service. + - publication_service # NGINX зависит от запуска publication_service. \ No newline at end of file diff --git a/lazarev_andrey_lab_3/nginx.conf b/lazarev_andrey_lab_3/nginx.conf new file mode 100644 index 0000000..b98a188 --- /dev/null +++ b/lazarev_andrey_lab_3/nginx.conf @@ -0,0 +1,27 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 8000; + listen [::]:8000; + server_name localhost; + + location /author_service/ { + proxy_pass http://author_service:8008/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Prefix $scheme; + } + + location /publication_service/ { + proxy_pass http://publication_service:8009/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Prefix $scheme; + } + } +} \ No newline at end of file diff --git a/lazarev_andrey_lab_3/publication_service/Dockerfile b/lazarev_andrey_lab_3/publication_service/Dockerfile new file mode 100644 index 0000000..8b7e4a6 --- /dev/null +++ b/lazarev_andrey_lab_3/publication_service/Dockerfile @@ -0,0 +1,12 @@ +#описание в Dockerfile author_service +FROM python:3.10-slim + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY publication_service/main.py . + +CMD ["python", "main.py"] \ No newline at end of file diff --git a/lazarev_andrey_lab_3/publication_service/main.py b/lazarev_andrey_lab_3/publication_service/main.py new file mode 100644 index 0000000..ad5c239 --- /dev/null +++ b/lazarev_andrey_lab_3/publication_service/main.py @@ -0,0 +1,113 @@ +from fastapi import FastAPI, HTTPException +from fastapi.responses import JSONResponse +from pydantic import BaseModel, Field +from uuid import UUID, uuid4 +import requests + +#Инициализация веб-приложения +app = FastAPI(title="Publication service") + +#Строка подключения к авторам +author_url='http://author_service:8008' + +#Сущность публикации с полями название, год публикации, ид автора. +class Publication(BaseModel): + uuid_: UUID = Field(default_factory=uuid4) + name: str | None + public_year: int | None + author_id: UUID | None + +#Заранее заполненный список публикаций, в некоторых есть uuid они пригодятся при создании публикаций +data: list[Publication] = [ + Publication(uuid_="92e78b56-0026-4561-b9f6-ba628110c901", name="книга 1", public_year=2024, author_id="92e78b56-0026-4561-b9f6-ba628110c900"), + Publication(name="книга 2", public_year=2022, author_id="92e78b56-0026-4561-b9f6-ba628110c900"), + Publication(name="книга 3", public_year=2003, author_id="3203b355-d844-4d5a-ad91-a9e0135cd9d9"), + Publication(name="книга 4", public_year=2020, author_id="92e78b56-0026-4561-b9f6-ba628110c900"), + Publication(name="книга 5", public_year=2019, author_id="3203b355-d844-4d5a-ad91-a9e0135cd9d9") +] + +#Получить список всех публикаций +@app.get("/publication", tags=["Publication"]) +def all_publications(): + return data + + +#Получить одной публикации по uuid +@app.get("/publication/{publication_id}", tags=["Publication"]) +def get_publication(publication_id: UUID): + publication = next((x for x in data if x.uuid_ == publication_id), None) + + if not publication: + return HTTPException(status_code=404, detail="Публикация не найдена") + + return publication + +#Получить одной публикации по uuid с информацие об ее авторе +@app.get("/publication/full/{publication_id}") +def get_full_publication(publication_id: UUID): + publication = get_publication(publication_id) + + if not publication: + return HTTPException(status_code=404, detail="Публикаций не найдена") + + author = requests.get(f"{author_url}/author/{publication.author_id}") + + if not author: + return HTTPException(status_code=404, detail="Автор не найден") + + result = publication.model_dump() + result['author_info'] = author.json() + + return result + +#Добавление новой публикации, все поля обязательные +@app.post("/publication", tags=["Publication"]) +def add_publication(name: str, public_year: int, author_id: UUID): + author = next((x for x in data if x.name == name and x.public_year == public_year and x.author_id == author_id), None) + + if author: + return HTTPException(status_code=404, detail="Такая публикация уже существует") + + try: + data.append(Publication(name=name, public_year=public_year, author_id=author_id)) + return JSONResponse(content={"message": "Публикация успешно добавлена"}, status_code=200) + + except Exception as e: + return HTTPException(status_code=404, detail={"Публикация не была добавлена с ошибкой": str(e)}) + +#Изменение публикации по uuid +@app.put("/publication/{publication_id}", tags=["Publication"]) +def update_publication(publication_id: UUID, name: str = None, public_year: int = None, author_id: UUID = None): + publication = get_publication(publication_id) + + if publication: + index = data.index(publication) + if name: + data[index].name = name + if public_year: + data[index].public_year = public_year + if author_id: + data[index].author_id = author_id + return JSONResponse(content={"message": "Публикация успешно изменена"}, status_code=200) + + else: + return HTTPException(status_code=404, detail={"Публикация не найдена": {publication}}) + +#Удаление публикации по uuid +@app.delete("/publication/{publication_id}", tags=["Publication"]) +def delete_publication(publication_id: UUID): + publication = get_publication(publication_id) + + if publication: + index = data.index(publication) + del data[index] + + return JSONResponse(content={"message": "Публикация успешно удалена"}, status_code=200) + + else: + return HTTPException(status_code=404, detail={"Публикация не найдена": {publication}}) + +#Запуск +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8009) \ No newline at end of file diff --git a/lazarev_andrey_lab_3/requirements.txt b/lazarev_andrey_lab_3/requirements.txt new file mode 100644 index 0000000..5378a0d --- /dev/null +++ b/lazarev_andrey_lab_3/requirements.txt @@ -0,0 +1,5 @@ +fastapi==0.115.0 +uvicorn==0.31.0 +pydantic==2.9.2 +pydantic_core==2.23.4 +requests==2.32.3 \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/.gitignore b/rogashova_ekaterina_lab_2/.gitignore new file mode 100644 index 0000000..4f1f6fc --- /dev/null +++ b/rogashova_ekaterina_lab_2/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.pyc +*.pyo +*.log +.DS_Store \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/data/name.txt b/rogashova_ekaterina_lab_2/data/name.txt new file mode 100644 index 0000000..7fd5724 --- /dev/null +++ b/rogashova_ekaterina_lab_2/data/name.txt @@ -0,0 +1 @@ +1 67 11 45 \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/data/namename.txt b/rogashova_ekaterina_lab_2/data/namename.txt new file mode 100644 index 0000000..7e92570 --- /dev/null +++ b/rogashova_ekaterina_lab_2/data/namename.txt @@ -0,0 +1 @@ +1 2 3 4 5 \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/docker-compose.yml b/rogashova_ekaterina_lab_2/docker-compose.yml new file mode 100644 index 0000000..5687f7f --- /dev/null +++ b/rogashova_ekaterina_lab_2/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' + +services: + findfile: + build: + context: ./worker-1 + volumes: + - ./data:/var/data + - ./result:/var/result + + findnumber: + build: + context: ./worker-2 + volumes: + - ./result:/var/result + depends_on: + - findfile \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/readme.md b/rogashova_ekaterina_lab_2/readme.md new file mode 100644 index 0000000..9e32c6f --- /dev/null +++ b/rogashova_ekaterina_lab_2/readme.md @@ -0,0 +1,30 @@ +# Лабораторная работа №2 + +#### Вариант 1 сервиса: 5. Ищет в каталоге /var/data файл с самым коротким названием и перекладывает его в /var/result/data.txt. + +#### Вариант 2 сервиса: 1. Ищет набольшее число из файла /var/data/data.txt и сохраняет его вторую степень в /var/result/result.txt. + +## Ход работы: +1. Создаем необходимые директории с файлами - программами на языке Python, которые выполняют необходимые действия по варианту. +Программа 1: +Принимает каталог в качестве входных данных и находит файл с самым коротким названием в этом катологе. Затем перемещает его в другой каталог. +Программа 2: +Принимает на вход файл с целыми числами, находит наибольшее и возводит его в квадрат. Результат выводит в новый файл. +2. Создаем файл docker-compose.yml. +Здесь происходит настройка зависимостей между сервисами, гарантируя, что 2 программа запустится только после 1. Он также настраивает монтирование папок, чтобы программы имели доступ к каталогам и файлам. +3. Также в папку с каждой программой необходимо добавить Dockerfile. Dockerfile — это текстовый файл, который содержит инструкции по сборке образа Docker. Он используется для создания настраиваемых образов Docker, которые могут запускать ваши приложения в изолированной и воспроизводимой среде. + +## Как запустить это? + +Для запуска данной конфигурации Docker Compose выполните следующие шаги: + +1. Открыть терминал и перейти в директорию, где находится docker-compose.yml. +2. Выполнить команду +Выполнить команду: +``` +docker compose up --build +``` +3. Дождаться, пока Docker Compose запустит все контейнеры. + +## Видео +Работоспособность представлена на [видео](https://vk.com/video204968285_456240925). \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/worker-1/Dockerfile b/rogashova_ekaterina_lab_2/worker-1/Dockerfile new file mode 100644 index 0000000..0e6d262 --- /dev/null +++ b/rogashova_ekaterina_lab_2/worker-1/Dockerfile @@ -0,0 +1,11 @@ +# Используем базовый образ с Python +FROM python:3.9-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файл с кодом программы в контейнер +COPY findfile.py . + +# Запускаем приложение +CMD ["python", "findfile.py"] \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/worker-1/findfile.py b/rogashova_ekaterina_lab_2/worker-1/findfile.py new file mode 100644 index 0000000..d8706ed --- /dev/null +++ b/rogashova_ekaterina_lab_2/worker-1/findfile.py @@ -0,0 +1,23 @@ +import os +import shutil + +def find_shortest_file(directory): + shortest_file = None + shortest_file_length = float('inf') + for file in os.listdir(directory): + file_path = os.path.join(directory, file) + if os.path.isfile(file_path) and len(file) < shortest_file_length: + shortest_file = file_path + shortest_file_length = len(file) + return shortest_file + +def move_file(source, destination): + shutil.move(source, destination) + +directory = "/var/data" + +shortest_file = find_shortest_file(directory) + +if shortest_file is not None: + destination = "/var/result/data.txt" + move_file(shortest_file, destination) diff --git a/rogashova_ekaterina_lab_2/worker-2/Dockerfile b/rogashova_ekaterina_lab_2/worker-2/Dockerfile new file mode 100644 index 0000000..46651e0 --- /dev/null +++ b/rogashova_ekaterina_lab_2/worker-2/Dockerfile @@ -0,0 +1,11 @@ +# Используем базовый образ с Python +FROM python:3.9-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файл с кодом программы в контейнер +COPY findnumber.py . + +# Запускаем приложение +CMD ["python", "findnumber.py"] \ No newline at end of file diff --git a/rogashova_ekaterina_lab_2/worker-2/findnumber.py b/rogashova_ekaterina_lab_2/worker-2/findnumber.py new file mode 100644 index 0000000..e0fbd0f --- /dev/null +++ b/rogashova_ekaterina_lab_2/worker-2/findnumber.py @@ -0,0 +1,29 @@ +import os + +def find_max_number(file_path): + max_number = float('-inf') + with open(file_path, "r") as f: + # Читаем все строки из файла + content = f.read() + # Разделяем строки по пробелам для получения списка чисел + numbers = map(int, content.split()) + for number in numbers: + if number > max_number: + max_number = number + return max_number + +def save_result(result, file_path): + with open(file_path, "w") as f: + f.write(str(result)) + +def print_result(result): + print("Квадрат наибольшего числа:", result) + +file_path = "/var/result/data.txt" + +max_number = find_max_number(file_path) + +result_file_path = "/var/result/result.txt" +save_result(max_number ** 2, result_file_path) + +print_result(max_number ** 2) diff --git a/rogashova_ekaterina_lab_3/.gitignore b/rogashova_ekaterina_lab_3/.gitignore new file mode 100644 index 0000000..eb53ea0 --- /dev/null +++ b/rogashova_ekaterina_lab_3/.gitignore @@ -0,0 +1,2 @@ +/.venv +/.idea \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/docker-compose.yml b/rogashova_ekaterina_lab_3/docker-compose.yml new file mode 100644 index 0000000..581d984 --- /dev/null +++ b/rogashova_ekaterina_lab_3/docker-compose.yml @@ -0,0 +1,27 @@ +services: + + task_service: + container_name: task_service + build: + context: . + dockerfile: ./task_service/Dockerfile + expose: + - 8081 + + teacher_service: + container_name: teacher_service + build: + context: . + dockerfile: ./teacher_service/Dockerfile + expose: + - 8082 + + nginx: + image: nginx:latest + ports: + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - task_service + - teacher_service \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/nginx.conf b/rogashova_ekaterina_lab_3/nginx.conf new file mode 100644 index 0000000..a5f11e7 --- /dev/null +++ b/rogashova_ekaterina_lab_3/nginx.conf @@ -0,0 +1,25 @@ +events { worker_connections 1024; } + +http { + server { + listen 80; + listen [::]:80; + server_name localhost; + + location /task_service/ { + proxy_pass http://task_service:8081/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /teacher_service/ { + proxy_pass http://teacher_service:8082/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/readme.md b/rogashova_ekaterina_lab_3/readme.md new file mode 100644 index 0000000..5e3689e --- /dev/null +++ b/rogashova_ekaterina_lab_3/readme.md @@ -0,0 +1,37 @@ +# Лабораторная работа №3 + +## Описание +Были использованы следующие сущности: +1. Учитель. Поля: email и ФИО +2. Задание. Поля: название, предмет и id учителя + +Сущности связаны связью один ко многим. У одного учителя может быть несколько заданий, у задания только один учитель. + +Для каждой сущности был написан отдельный сервис. + +Код каждого сервиса представляет собой полноценное API для работы с задачами и учителями. +Они включают основные операции CRUD (создание, чтение, обновление, удаление). Дополнительно можно вывести задачу с полной информацией об учителе. + +В качестве хранилища данных использовалась оперативная память приложения. + +Запросы к сервисам проксирует шлюз на основе Nginx. Для этого перед запуском nginx был описан конфигурационный файл nginx.conf, +в котором описан прослушиваемый порт и название сервера (в блоке server), маршруты до микросервисов и параметры проксирования (в блоке location). + +Конфигурация Nginx направлена на организацию и упрощение работы с микросервисами. + +Тестирование производится через расширение RestMan. + +## Как запустить это? + +Для запуска данной конфигурации Docker Compose выполните следующие шаги: + +1. Открыть терминал и перейти в директорию, где находится docker-compose.yml. +2. Выполнить команду +``` +docker compose up --build +``` +3. Дождаться, пока Docker Compose запустит все контейнеры. + + +## Видео +Работоспособность представлена на [видео](https://vk.com/video204968285_456240927). \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/requirements.txt b/rogashova_ekaterina_lab_3/requirements.txt new file mode 100644 index 0000000..494909e --- /dev/null +++ b/rogashova_ekaterina_lab_3/requirements.txt @@ -0,0 +1,2 @@ +Flask==3.0.3 +requests==2.32.3 \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/task_service/Dockerfile b/rogashova_ekaterina_lab_3/task_service/Dockerfile new file mode 100644 index 0000000..40f31ce --- /dev/null +++ b/rogashova_ekaterina_lab_3/task_service/Dockerfile @@ -0,0 +1,17 @@ +# Используем базовый образ Python +FROM python:3.12-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файл requirements.txt в контейнер +COPY requirements.txt . + +# Устанавливаем зависимости +RUN pip install --no-cache-dir -r requirements.txt + +# Копируем все файлы в контейнер +COPY task_service/task_service.py . + +# Команда для запуска Python-скрипта +CMD ["python", "task_service.py"] \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/task_service/task_service.py b/rogashova_ekaterina_lab_3/task_service/task_service.py new file mode 100644 index 0000000..d2a2f79 --- /dev/null +++ b/rogashova_ekaterina_lab_3/task_service/task_service.py @@ -0,0 +1,119 @@ +from flask import Flask, jsonify, request, abort +import uuid +import requests + +app = Flask(__name__) + +tasks = {} +teachers = {} + +@app.route('/tasks', methods=['GET']) +def get_tasks(): + # Получаем все задачи, но только с teacher_id. + return jsonify(list(tasks.values())) + +@app.route('/tasks_with_teachers', methods=['GET']) +def get_tasks_with_teachers(): + tasks_with_teachers = [] + + for task in tasks.values(): + teacher_id = task.get('teacher_id') + teacher_info = None + + if teacher_id: + try: + # Запрос информации об учителе + teacher_response = requests.get(f'http://teacher_service:8082/teachers/{teacher_id}') + if teacher_response.status_code == 200: + teacher_details = teacher_response.json() + # Формируем объект с нужной информацией об учителе + teacher_info = { + "fio": teacher_details.get("fio"), + "email": teacher_details.get("email") + } + except requests.exceptions.RequestException as e: + print(f"Error fetching teacher: {e}") + + # Формируем ответ с нужной структурой + tasks_with_teachers.append({ + 'id': task.task_id, + 'title': task.get('title'), + 'subject': task.get('subject'), + 'teacher_id': task.get('teacher_id'), + 'teacherInfo': teacher_info # Упрощенная информация об учителе + }) + + return jsonify(tasks_with_teachers) + +@app.route('/tasks/', methods=['GET']) +def get_task(task_id): + task = tasks.get(task_id) + if task is None: + abort(404) + + return jsonify(task) + +@app.route('/task_with_teacher/', methods=['GET']) +def get_task_with_teacher(task_id): + task = tasks.get(task_id) + if task is None: + abort(404) + + # Получаем информацию о назначенном учителе из teacher_service + teacher_info = None + teacher_id = task.get('teacher_id') + if teacher_id: + try: + teacher_response = requests.get(f'http://teacher_service:8082/teachers/{teacher_id}') + if teacher_response.status_code == 200: + teacher_details = teacher_response.json() + # Формируем объект с нужной информацией об учителе + teacher_info = { + "fio": teacher_details.get("fio"), + "email": teacher_details.get("email") + } + except requests.exceptions.RequestException as e: + print(f"Error fetching teacher: {e}") + + # Формируем ответ с нужной структурой + response = { + "id": task_id, # id задания + "title": task.get('title'), + "subject": task.get('subject'), + "teacher_id": teacher_id, + "teacherInfo": teacher_info # Упрощенная информация об учителе + } + + return jsonify(response) + +@app.route('/tasks', methods=['POST']) +def create_task(): + data = request.get_json() + task_id = str(uuid.uuid4()) + tasks[task_id] = { + 'id': task_id, + 'title': data['title'], + 'subject': data['subject'], + 'teacher_id': data['teacher_id'] # Принимаем teacher_id из запроса + } + return jsonify(tasks[task_id]), 201 + +@app.route('/tasks/', methods=['PUT']) +def update_task(task_id): + data = request.get_json() + task = tasks.get(task_id) + if task is None: + abort(404) + task['title'] = data.get('title', task['title']) + task['subject'] = data.get('subject', task['subject']) + return jsonify(task) + +@app.route('/tasks/', methods=['DELETE']) +def delete_task(task_id): + task = tasks.pop(task_id, None) + if task is None: + abort(404) + return '', 200 + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8081) diff --git a/rogashova_ekaterina_lab_3/teacher_service/Dockerfile b/rogashova_ekaterina_lab_3/teacher_service/Dockerfile new file mode 100644 index 0000000..a3bfc57 --- /dev/null +++ b/rogashova_ekaterina_lab_3/teacher_service/Dockerfile @@ -0,0 +1,17 @@ +# Используем базовый образ Python +FROM python:3.12-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файл requirements.txt в контейнер +COPY requirements.txt . + +# Устанавливаем зависимости +RUN pip install --no-cache-dir -r requirements.txt + +# Копируем все файлы в контейнер +COPY teacher_service/teacher_service.py . + +# Команда для запуска Python-скрипта +CMD ["python", "teacher_service.py"] \ No newline at end of file diff --git a/rogashova_ekaterina_lab_3/teacher_service/teacher_service.py b/rogashova_ekaterina_lab_3/teacher_service/teacher_service.py new file mode 100644 index 0000000..2c39cd0 --- /dev/null +++ b/rogashova_ekaterina_lab_3/teacher_service/teacher_service.py @@ -0,0 +1,48 @@ +from flask import Flask, jsonify, request, abort +import uuid + +app = Flask(__name__) + +teachers = {} + +@app.route('/teachers', methods=['GET']) +def get_teachers(): + return jsonify(list(teachers.values())) + +@app.route('/teachers/', methods=['GET']) +def get_teacher(teacher_id): + teacher = teachers.get(teacher_id) + if teacher is None: + abort(404) + return jsonify(teacher) + +@app.route('/teachers', methods=['POST']) +def create_teacher(): + data = request.get_json() + teacher_id = str(uuid.uuid4()) + teachers[teacher_id] = { + 'id': teacher_id, + 'fio': data['fio'], + 'email': data['email'] + } + return jsonify(teachers[teacher_id]), 201 + +@app.route('/teachers/', methods=['PUT']) +def update_teacher(teacher_id): + data = request.get_json() + teacher = teachers.get(teacher_id) + if teacher is None: + abort(404) + teacher['fio'] = data.get('fio', teacher['fio']) + teacher['email'] = data.get('email', teacher['email']) + return jsonify(teacher) + +@app.route('/teachers/', methods=['DELETE']) +def delete_teacher(teacher_id): + teacher = teachers.pop(teacher_id, None) + if teacher is None: + abort(404) + return '', 200 + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8082) diff --git a/tsukanova_irina_lab_5/README.md b/tsukanova_irina_lab_5/README.md new file mode 100644 index 0000000..a15ed43 --- /dev/null +++ b/tsukanova_irina_lab_5/README.md @@ -0,0 +1,16 @@ +# Цуканова Ирина ПИбд-42 +# Лабораторная работа №5 - Параллельное перемножение матриц + + +## Результат: +![results](./img.png) + +## Выводы: + +1. Для маленьких матриц выгоднее использовать последовательное умножение (1 поток) +2. Для больших матриц лучше использовать параллельное умножение, так как временные затраты +последовательного умножения в этом случае существенно выше, чем затраты на управление потоками. +3. Увеличение количества потоков для осуществления умножения больших матриц в определенный момент не дает +прироста в скорости выполнения. Это значит, что достигнуто оптимальное количество потоков. + +## [Видео](https://drive.google.com/file/d/1pMMKllM24xwXZlQkY9VIuKSeKr5vpUHI/view?usp=sharing) \ No newline at end of file diff --git a/tsukanova_irina_lab_5/img.png b/tsukanova_irina_lab_5/img.png new file mode 100644 index 0000000..52dd803 Binary files /dev/null and b/tsukanova_irina_lab_5/img.png differ diff --git a/tsukanova_irina_lab_5/main.py b/tsukanova_irina_lab_5/main.py new file mode 100644 index 0000000..eb9627a --- /dev/null +++ b/tsukanova_irina_lab_5/main.py @@ -0,0 +1,55 @@ +import multiprocessing +import time +from time import time + +import numpy as np + + +def matrix_multi(first, second, res, start_i, stop_i, size): + for i in range(start_i, stop_i): + for j in range(size): + res[i][j] = 0 + for k in range(size): + res[i][j] += first[i][k] * second[k][j] + + +def do(first, second, size, threads): + offset = int(size / threads) + offset_last = size % threads + offset + + processes = [] + res = np.zeros((size, size)) + start_test = time() + for i in range(threads): + start_ = i * offset + stop_ = start_ + offset_last if i == threads - 1 else start_ + offset + + process = multiprocessing.Process(target=matrix_multi, args=(first, second, res, start_, stop_, size)) + processes.append(process) + process.start() + + for p in processes: + p.join() + stop_test = time() + print(f'{size}x{size}, time: {stop_test - start_test}') + + +if __name__ == "__main__": + sizes = [100, 300, 500] + threads_counts = [1, 4, 6, 8, 12] + for threads in threads_counts: + print('-------------------------------------------------') + print(f'Threads:{threads}') + for n in sizes: + first_matrix = np.random.randint(3, size=(n, n)) + second_matrix = np.random.randint(3, size=(n, n)) + if threads == 1: + res = np.zeros((n, n)) + start = time() + matrix_multi(first_matrix, second_matrix, res, 0, n, n) + stop = time() + print(f'{n}x{n}, time: {stop - start}') + else: + do(first_matrix, second_matrix, n, threads) + + print('-------------------------------------------------') diff --git a/tukaeva_alfiya_lab_4/.idea/.gitignore b/tukaeva_alfiya_lab_4/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/Project_Default.xml b/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..f966c2e --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/profiles_settings.xml b/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/.idea/misc.xml b/tukaeva_alfiya_lab_4/.idea/misc.xml new file mode 100644 index 0000000..442f653 --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/.idea/modules.xml b/tukaeva_alfiya_lab_4/.idea/modules.xml new file mode 100644 index 0000000..9af9c9d --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/.idea/tukaeva_alfiya_lab_4.iml b/tukaeva_alfiya_lab_4/.idea/tukaeva_alfiya_lab_4.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/tukaeva_alfiya_lab_4.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/.idea/vcs.xml b/tukaeva_alfiya_lab_4/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/tukaeva_alfiya_lab_4/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/1_lesson/receive.py b/tukaeva_alfiya_lab_4/1_lesson/receive.py new file mode 100644 index 0000000..f118e0a --- /dev/null +++ b/tukaeva_alfiya_lab_4/1_lesson/receive.py @@ -0,0 +1,25 @@ +import pika, sys, os + +def main(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + + channel.queue_declare(queue='hello') + + def callback(ch, method, properties, body): + print(f" [x] Received {body}") + + channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True) + + print(' [*] Waiting for messages. To exit press CTRL+C') + channel.start_consuming() + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print('Interrupted') + try: + sys.exit(0) + except SystemExit: + os._exit(0) \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/1_lesson/send.py b/tukaeva_alfiya_lab_4/1_lesson/send.py new file mode 100644 index 0000000..41cfff2 --- /dev/null +++ b/tukaeva_alfiya_lab_4/1_lesson/send.py @@ -0,0 +1,11 @@ +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() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/2_lesson/new_task.py b/tukaeva_alfiya_lab_4/2_lesson/new_task.py new file mode 100644 index 0000000..a2444e0 --- /dev/null +++ b/tukaeva_alfiya_lab_4/2_lesson/new_task.py @@ -0,0 +1,19 @@ +import pika +import sys + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost')) +channel = connection.channel() + +channel.queue_declare(queue='task_queue', durable=True) + +message = ' '.join(sys.argv[1:]) or "Hello World!" +channel.basic_publish( + exchange='', + routing_key='task_queue', + body=message, + properties=pika.BasicProperties( + delivery_mode=pika.DeliveryMode.Persistent + )) +print(f" [x] Sent {message}") +connection.close() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/2_lesson/worker.py b/tukaeva_alfiya_lab_4/2_lesson/worker.py new file mode 100644 index 0000000..34cb8f7 --- /dev/null +++ b/tukaeva_alfiya_lab_4/2_lesson/worker.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +import pika +import time + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost')) +channel = connection.channel() + +channel.queue_declare(queue='task_queue', durable=True) +print(' [*] Waiting for messages. To exit press CTRL+C') + + +def callback(ch, method, properties, body): + print(f" [x] Received {body.decode()}") + time.sleep(body.count(b'.')) + print(" [x] Done") + ch.basic_ack(delivery_tag=method.delivery_tag) + + +channel.basic_qos(prefetch_count=1) +channel.basic_consume(queue='task_queue', on_message_callback=callback) + +channel.start_consuming() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/3_lesson/emit_log.py b/tukaeva_alfiya_lab_4/3_lesson/emit_log.py new file mode 100644 index 0000000..45b6989 --- /dev/null +++ b/tukaeva_alfiya_lab_4/3_lesson/emit_log.py @@ -0,0 +1,13 @@ +import pika +import sys + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost')) +channel = connection.channel() + +channel.exchange_declare(exchange='logs', exchange_type='fanout') + +message = ' '.join(sys.argv[1:]) or "info: Hello World!" +channel.basic_publish(exchange='logs', routing_key='', body=message) +print(f" [x] Sent {message}") +connection.close() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/3_lesson/receive_logs.py b/tukaeva_alfiya_lab_4/3_lesson/receive_logs.py new file mode 100644 index 0000000..60d881d --- /dev/null +++ b/tukaeva_alfiya_lab_4/3_lesson/receive_logs.py @@ -0,0 +1,22 @@ +import pika + +connection = pika.BlockingConnection( + pika.ConnectionParameters(host='localhost')) +channel = connection.channel() + +channel.exchange_declare(exchange='logs', exchange_type='fanout') + +result = channel.queue_declare(queue='', exclusive=True) +queue_name = result.method.queue + +channel.queue_bind(exchange='logs', queue=queue_name) + +print(' [*] Waiting for logs. To exit press CTRL+C') + +def callback(ch, method, properties, body): + print(f" [x] {body}") + +channel.basic_consume( + queue=queue_name, on_message_callback=callback, auto_ack=True) + +channel.start_consuming() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/Consumer_1.py b/tukaeva_alfiya_lab_4/Consumer_1.py new file mode 100644 index 0000000..2018626 --- /dev/null +++ b/tukaeva_alfiya_lab_4/Consumer_1.py @@ -0,0 +1,26 @@ +import random +import time +import pika + +queue_name = 'queue_1' +exchange = 'logs' + + +def callback(ch, method, properties, body): + print(f" [Consumer_1] - получено сообщение - {body.decode()}") + time.sleep(random.choice([2, 3])) + print(f" [Consumer_1] - сообщение обработано") + print() + ch.basic_ack(delivery_tag=method.delivery_tag) + + +if __name__ == '__main__': + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + try: + channel.queue_declare(queue=queue_name) + channel.queue_bind(exchange=exchange, queue=queue_name) + channel.basic_consume(queue=queue_name, on_message_callback=callback) + channel.start_consuming() + except KeyboardInterrupt: + connection.close() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/Consumer_2.py b/tukaeva_alfiya_lab_4/Consumer_2.py new file mode 100644 index 0000000..533fac8 --- /dev/null +++ b/tukaeva_alfiya_lab_4/Consumer_2.py @@ -0,0 +1,25 @@ +import pika + +queue_name = 'queue_2' +exchange = 'logs' + + +def callback(ch, method, properties, body): + print(f" [Consumer_2] - получено сообщение - {body.decode()}") + print(f" [Consumer_2] - сообщение обработано") + print() + ch.basic_ack(delivery_tag=method.delivery_tag) + + +if __name__ == '__main__': + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + try: + # своя не анонимная очередь + channel.queue_declare(queue=queue_name) + # binding на exchange + channel.queue_bind(exchange=exchange, queue=queue_name) + channel.basic_consume(queue=queue_name, on_message_callback=callback) + channel.start_consuming() + except KeyboardInterrupt: + connection.close() diff --git a/tukaeva_alfiya_lab_4/Publisher.py b/tukaeva_alfiya_lab_4/Publisher.py new file mode 100644 index 0000000..6f6efb2 --- /dev/null +++ b/tukaeva_alfiya_lab_4/Publisher.py @@ -0,0 +1,17 @@ +import random +import time + +import pika + +if __name__ == '__main__': + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + channel.exchange_declare(exchange='logs', exchange_type='fanout') + + try: + while True: + message = random.choice(['SIGABRT', 'SIGALRM', 'SIGKILL', 'SIGSTOP', 'SIGTERM', 'SIGINT', 'SIGQUIT']) + channel.basic_publish(exchange='logs', routing_key='', body=message) + time.sleep(1) + except KeyboardInterrupt: + connection.close() \ No newline at end of file diff --git a/tukaeva_alfiya_lab_4/README.md b/tukaeva_alfiya_lab_4/README.md new file mode 100644 index 0000000..e290983 --- /dev/null +++ b/tukaeva_alfiya_lab_4/README.md @@ -0,0 +1,53 @@ +# Лабораторная работа №4 - Работа с брокером сообщений + +## Задание + + +* Установить брокер сообщений RabbitMQ. +* Пройти уроки 1, 2 и 3 из RabbitMQ Tutorials на любом языке программирования. +* Продемонстрировать работу брокера сообщений. + +## Работа программы: + +Класс ```Publisher``` успешно осуществляет отправку сообщений своим клиентам. + +Класс ```Consumer1``` осуществляет принятие и обработку сообщений с задержкой в 3 секунды, это можно заметить на видео. + +Класс ```Consumer2``` мгновенно осуществляет принятие и обработку сообщений. + +### Уроки + + 1. lesson_1 + +![](lesson_1.png "") + + 2. lesson_2 + +![](lesson_2.png "") + + 3. lesson_3 + +![](lesson_3.png "") + +## Работа с RabbitMQ Management UI + +![](rabbitmq.png "") + +### Показания очереди queue_1 при одном запущенном экземпляре Consumer_1 + +![](queue_1_1.png "") + +### Показания очереди queue_2 + +![](queue_2.png "") + +### Показания очереди queue_1 при двух запущенных экземплярах Consumer_1 + +![](queue_1_2.png "") + +### Показания очереди queue_1 при трех запущенных экземплярах Consumer_1 + +![](queue_1_3.png "") + +# Видео +https://vk.com/video230744264_456239106?list=ln-JCuDuG12swuj6vibPz diff --git a/tukaeva_alfiya_lab_4/lesson_1.png b/tukaeva_alfiya_lab_4/lesson_1.png new file mode 100644 index 0000000..d4a339d Binary files /dev/null and b/tukaeva_alfiya_lab_4/lesson_1.png differ diff --git a/tukaeva_alfiya_lab_4/lesson_2.png b/tukaeva_alfiya_lab_4/lesson_2.png new file mode 100644 index 0000000..1516aab Binary files /dev/null and b/tukaeva_alfiya_lab_4/lesson_2.png differ diff --git a/tukaeva_alfiya_lab_4/lesson_3.png b/tukaeva_alfiya_lab_4/lesson_3.png new file mode 100644 index 0000000..4814988 Binary files /dev/null and b/tukaeva_alfiya_lab_4/lesson_3.png differ diff --git a/tukaeva_alfiya_lab_4/queue_1_1.png b/tukaeva_alfiya_lab_4/queue_1_1.png new file mode 100644 index 0000000..d541247 Binary files /dev/null and b/tukaeva_alfiya_lab_4/queue_1_1.png differ diff --git a/tukaeva_alfiya_lab_4/queue_1_2.png b/tukaeva_alfiya_lab_4/queue_1_2.png new file mode 100644 index 0000000..609e51c Binary files /dev/null and b/tukaeva_alfiya_lab_4/queue_1_2.png differ diff --git a/tukaeva_alfiya_lab_4/queue_1_3.png b/tukaeva_alfiya_lab_4/queue_1_3.png new file mode 100644 index 0000000..bb8063f Binary files /dev/null and b/tukaeva_alfiya_lab_4/queue_1_3.png differ diff --git a/tukaeva_alfiya_lab_4/queue_2.png b/tukaeva_alfiya_lab_4/queue_2.png new file mode 100644 index 0000000..3bbca99 Binary files /dev/null and b/tukaeva_alfiya_lab_4/queue_2.png differ diff --git a/tukaeva_alfiya_lab_4/rabbitmq.png b/tukaeva_alfiya_lab_4/rabbitmq.png new file mode 100644 index 0000000..9102864 Binary files /dev/null and b/tukaeva_alfiya_lab_4/rabbitmq.png differ diff --git a/tukaeva_alfiya_lab_5/README.md b/tukaeva_alfiya_lab_5/README.md new file mode 100644 index 0000000..086c7aa --- /dev/null +++ b/tukaeva_alfiya_lab_5/README.md @@ -0,0 +1,30 @@ +# Лабораторная работа №5 - Параллельное умножение матриц + +## Задание + + +* Кратко: реализовать умножение двух больших квадратных матриц. + +* Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +## Работа программы: + + 1. Генерируются случайные матрицы A и B заданных размеров. + + 2. multiply_matrices_sequential(A, B) умножает две матрицы A и B последовательно, используя вложенные циклы для вычисления элементов результирующей матрицы C. + + 3. multiply_matrices_parallel(A, B, num_workers) выполняет параллельное умножение матриц с использованием пула процессов. + + 4. benchmark(matrix_size, num_workers) Измеряет время выполнения операций умножения. И выводит результат в консоль. + +### Результат: + +![](result.png "") + +### Вывод: + +Параллельный подход может быть более быстрым, чем последовательный на матрицах большого размера, так как он позволяет производить более эффективное распределение работы между процессами. Однако на маленьких матрицах небольшая задержка на создание и инициализацию нескольких процессов может оказаться более затратным, чем просто выполнение умножения последовательно. + + +# Видео +https://vk.com/video230744264_456239107?list=ln-S0qfmD3VN0JZC8Nh6o diff --git a/tukaeva_alfiya_lab_5/project/main.py b/tukaeva_alfiya_lab_5/project/main.py new file mode 100644 index 0000000..3d159fb --- /dev/null +++ b/tukaeva_alfiya_lab_5/project/main.py @@ -0,0 +1,61 @@ +import numpy as np +import time +from multiprocessing import Pool + +def multiply_matrices_sequential(A, B): + """Последовательное умножение матриц.""" + n = A.shape[0] + C = np.zeros((n, n)) + for i in range(n): + for j in range(n): + C[i][j] = np.dot(A[i], B[:, j]) # Используем векторизированное умножение для повышения производительности + return C + +def worker(args): + """Функция для параллельного умножения матриц, которая обрабатывает строки.""" + A, B, row_indices = args + C_part = np.zeros((len(row_indices), B.shape[1])) + + for idx, i in enumerate(row_indices): + C_part[idx] = np.dot(A[i], B) + + return C_part + +def multiply_matrices_parallel(A, B, num_workers): + """Параллельное умножение матриц.""" + n = A.shape[0] + C = np.zeros((n, n)) + row_indices = np.array_split(range(n), num_workers) + + with Pool(processes=num_workers) as pool: + results = pool.map(worker, [(A, B, idx) for idx in row_indices]) + + # Объединяем результаты + for i, result in enumerate(results): + C[i * len(result): (i + 1) * len(result)] = result + + return C + +def benchmark(matrix_size, num_workers): + # Генерация случайных матриц + A = np.random.rand(matrix_size, matrix_size) + B = np.random.rand(matrix_size, matrix_size) + + start_time = time.time() + if num_workers == 1: + C = multiply_matrices_sequential(A, B) + else: + C = multiply_matrices_parallel(A, B, num_workers) + end_time = time.time() + + method = "последовательное" if num_workers == 1 else f"параллельное с {num_workers} потоками" + print(f"{method.capitalize()} умножение матриц {matrix_size}x{matrix_size}: {end_time - start_time:.6f} сек") + +if __name__ == "__main__": + # Запуск бенчмарков + sizes = [100, 300, 500] + for size in sizes: + print(f"\nБенчмарк для матриц размером {size}x{size}:") + benchmark(size, 1) # Последовательный + benchmark(size, 4) # Параллельный (4 потока) + benchmark(size, 8) # Параллельный (8 потоков) diff --git a/tukaeva_alfiya_lab_5/result.png b/tukaeva_alfiya_lab_5/result.png new file mode 100644 index 0000000..53bf718 Binary files /dev/null and b/tukaeva_alfiya_lab_5/result.png differ diff --git a/vaksman_valeria_lab_6/README.md b/vaksman_valeria_lab_6/README.md new file mode 100644 index 0000000..eca50b1 --- /dev/null +++ b/vaksman_valeria_lab_6/README.md @@ -0,0 +1,37 @@ +# Лабораторная работа 6. Определение детерминанта матрицы с помощью параллельных вычислений + +## Задание + +Требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять нахождение отдельной группы множителей. + +### Запуск программы + +Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать: +``` +python main.py +``` + +### Описание работы программы + +Программа реализует вычисление детерминанта квадратной матрицы с использованием двух алгоритмов: *обычного и параллельного*. + +  1. Обычный алгоритм + +      Использует функцию ```parallel_det``` для вычисления детерминанта. + +  2. Параллельный алгоритм + +      Разбивает матрицу на части и использует несколько потоков для параллельного вычисления детерминанта. Количество потоков задается вручную. Реализован с использованием библиотеки ```concurrent.futures```. + +Для каждого размера матрицы программа выводит время выполнения обычного и параллельного алгоритмов, а также соответствующие значения детерминантов. + +### Результат работы программы: + +![](result.png "") + +#### Вывод + +Параллельное выполнение нахождения детерминанта может привести к ускорению, особенно на больших матрицах. Однако, для некоторых матриц, результаты детерминантов могут отличаться между обычным и параллельным выполнением. + +# ВК +https://vk.com/video256017065_456239876 \ No newline at end of file diff --git a/vaksman_valeria_lab_6/docker-compose.yml b/vaksman_valeria_lab_6/docker-compose.yml new file mode 100644 index 0000000..15851d1 --- /dev/null +++ b/vaksman_valeria_lab_6/docker-compose.yml @@ -0,0 +1,9 @@ +services: + + project: + container_name: project + build: + context: . + dockerfile: ./project/Dockerfile + expose: + - 8008 diff --git a/vaksman_valeria_lab_6/project/Dockerfile b/vaksman_valeria_lab_6/project/Dockerfile new file mode 100644 index 0000000..9fd699f --- /dev/null +++ b/vaksman_valeria_lab_6/project/Dockerfile @@ -0,0 +1,11 @@ +# Использую базовый образ Python +FROM python:3.10-slim + +# Устанавливаю рабочую директорию внутри контейнера +WORKDIR /app + +# Копирую исполняемый файл +COPY project/main.py . + +# Команда для запуска Python-скрипта +CMD ["python", "main.py"] \ No newline at end of file diff --git a/vaksman_valeria_lab_6/project/main.py b/vaksman_valeria_lab_6/project/main.py new file mode 100644 index 0000000..82edb48 --- /dev/null +++ b/vaksman_valeria_lab_6/project/main.py @@ -0,0 +1,208 @@ +import random +import time +import copy +from multiprocessing import Pool +import concurrent.futures +from copy import deepcopy + + +class Matrix: + def __init__(self) -> None: + self.matrix_100 = [[0] * 100 for _ in range(100)] + self.matrix_300 = [[0] * 300 for _ in range(300)] + self.matrix_500 = [[0] * 500 for _ in range(500)] + + def str_matrix(self, type_list: str): + _str = "" + + current_matrix = getattr(self, type_list) + + for i in range(len(current_matrix)): + _str += "[ " + + for j in range(len(current_matrix[0])): + _str += str(current_matrix[i][j]) + " " + + _str += " ]\n" + + return _str + +# Глобальный объект класса для хранения результата работы потоков +result_matrix = copy.deepcopy(Matrix()) + +def init_matrix(matrix: Matrix, size: int): + support_list_main = [] + + for i in range(size): + support_list_column = [] + + for j in range(size): + support_list_column.append(random.randint(0, 5)) + + support_list_main.append(support_list_column) + + if size == 100: + matrix.matrix_100 = support_list_main + elif size == 300: + matrix.matrix_300 = support_list_main + elif size == 500: + matrix.matrix_500 = support_list_main + +# Функция параллельной обработки строк +def process_row(args): + i, j, m, n = args + + factor = m[j][i] / m[i][i] + + for k in range(i, n): + m[j][k] -= factor * m[i][k] + + return m[j] + +def parallel_det(matrix, num_threads=1): + n = len(matrix) + + # Создаем копию матрицы, чтобы не изменять исходную + m = deepcopy(matrix) + + det_value = 1 + + # Функция для параллельной обработки строк + def process_row(i, j): + factor = m[j][i] / m[i][i] + for k in range(i, n): + m[j][k] -= factor * m[i][k] + + for i in range(n): + # Поиск ненулевого элемента в текущем столбце для обмена строк + if m[i][i] == 0: + for j in range(i + 1, n): + if m[j][i] != 0: + m[i], m[j] = m[j], m[i] + + # Меняем знак определителя при обмене строк + det_value *= -1 + + break + else: + # Если все элементы в столбце равны 0, то определитель равен 0 + return 0 + + # Приведение матрицы к треугольному виду с использованием потоков + with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor: + # Параллельно обрабатываем строки ниже текущей (от i+1 до n) + futures = [ + executor.submit(process_row, i, j) for j in range(i + 1, n) + ] + concurrent.futures.wait(futures) + + # Умножаем на диагональный элемент + det_value *= m[i][i] + + return det_value + +def det(matrix): + n = len(matrix) + # копия матрицы для сохранения исходной + m = [row[:] for row in matrix] + det_value = 1 + + for i in range(n): + # Поиск ненулевого элемента в текущем столбце для обмена строк + if m[i][i] == 0: + for j in range(i + 1, n): + if m[j][i] != 0: + m[i], m[j] = m[j], m[i] + + # Меняем знак определителя при обмене строк + det_value *= -1 + + break + else: + return 0 # Если все элементы в столбце равны 0, то определитель равен 0 + + # Приведение матрицы к треугольному виду + for j in range(i + 1, n): + factor = m[j][i] / m[i][i] + + for k in range(i, n): + m[j][k] -= factor * m[i][k] + + # Умножаем на диагональный элемент + det_value *= m[i][i] + + return det_value + +def run_program(): + matrix = Matrix() + init_matrix(matrix, 100) + init_matrix(matrix, 300) + init_matrix(matrix, 500) + + start_time = time.time() + print(f"100x100:{det(matrix.matrix_100)}") + end_time = time.time() + print("Time 100x100: ", end_time - start_time) + + start_time = time.time() + print(f"100x100:{parallel_det(matrix.matrix_100, 3)}") + end_time = time.time() + print("Time 100x100: ", end_time - start_time) + + start_time = time.time() + print(f"100x100:{parallel_det(matrix.matrix_100, 5)}") + end_time = time.time() + print("Time 100x100: ", end_time - start_time) + + start_time = time.time() + print(f"100x100:{parallel_det(matrix.matrix_100, 8)}") + end_time = time.time() + print("Time 100x100: ", end_time - start_time) + + # ---------------------------------------------------------------------------------------------------- + print("\n" + "-" * 50 + "\n") + + start_time = time.time() + print(f"300x300:{det(matrix.matrix_300)}") + end_time = time.time() + print("Time 300x300: ", end_time - start_time) + + start_time = time.time() + print(f"300x300:{parallel_det(matrix.matrix_300, 3)}") + end_time = time.time() + print("Time 300x300: ", end_time - start_time) + + start_time = time.time() + print(f"300x300:{parallel_det(matrix.matrix_300, 5)}") + end_time = time.time() + print("Time 300x300: ", end_time - start_time) + + start_time = time.time() + print(f"300x300:{parallel_det(matrix.matrix_300, 8)}") + end_time = time.time() + print("Time 300x300: ", end_time - start_time) + + # ---------------------------------------------------------------------------------------------------- + print("\n" + "-" * 50 + "\n") + + start_time = time.time() + print(f"500x500:{det(matrix.matrix_500)}") + end_time = time.time() + print("Time 500x500: ", end_time - start_time) + + start_time = time.time() + print(f"500x500:{parallel_det(matrix.matrix_500, 3)}") + end_time = time.time() + print("Time 500x500: ", end_time - start_time) + + start_time = time.time() + print(f"500x500:{parallel_det(matrix.matrix_500, 5)}") + end_time = time.time() + print("Time 500x500: ", end_time - start_time) + + start_time = time.time() + print(f"500x500:{parallel_det(matrix.matrix_500, 8)}") + end_time = time.time() + print("Time 500x500: ", end_time - start_time) + +run_program() \ No newline at end of file diff --git a/vaksman_valeria_lab_6/result.png b/vaksman_valeria_lab_6/result.png new file mode 100644 index 0000000..328642e Binary files /dev/null and b/vaksman_valeria_lab_6/result.png differ diff --git a/vaksman_valeria_lab_7/README.md b/vaksman_valeria_lab_7/README.md new file mode 100644 index 0000000..a611ee3 --- /dev/null +++ b/vaksman_valeria_lab_7/README.md @@ -0,0 +1,21 @@ +# Лабораторная работа 7. Балансировка нагрузки в распределённых системах при помощи открытых технологий на примерах + +### Задание +Написать небольшое эссе (буквально несколько абзацев) своими словами (пожалуйста не пользуйтесь гуглом :). + +  1. Какие алгоритмы и методы используются для балансировки нагрузки? + +  2. Какие открытые технологии существуют для балансировки нагрузки? + +  3. Как осуществляется балансировка нагрузки на базах данных? + +  4. Реверс-прокси как один из элементов балансировки нагрузки. +*** +### Эссе +Балансировка нагрузки является важным аспектом в области информационных технологий, позволяющим равномерно распределять нагрузку между различными серверами или узлами системы. Для этого применяются различные алгоритмы и методы, такие как Round Robin, Least Connections, IP Hash и другие. Они позволяют эффективно управлять нагрузкой и избежать перегрузок на отдельных узлах. + +Существует множество открытых технологий для балансировки нагрузки, таких как Nginx, HAProxy, Apache HTTP Server и другие. Они позволяют настраивать и контролировать процесс балансировки нагрузки в зависимости от потребностей конкретной системы. + +Балансировка нагрузки на базах данных выполняется с использованием специальных алгоритмов, учитывающих объем данных, количество запросов и другие параметры. Это позволяет поддерживать стабильную работу баз данных, избегая перегрузок и сбоев. + +Реверс-прокси является одним из элементов балансировки нагрузки, который обеспечивает перенаправление запросов от клиентов к серверам. Он играет важную роль в обеспечении высокой доступности и быстрой отдачи данных, обеспечивая оптимальное использование ресурсов и повышая эффективность работы системы в целом. \ No newline at end of file diff --git a/vaksman_valeria_lab_8/README.md b/vaksman_valeria_lab_8/README.md new file mode 100644 index 0000000..4769ab5 --- /dev/null +++ b/vaksman_valeria_lab_8/README.md @@ -0,0 +1,26 @@ +# Лабораторная работа 8. Как Вы поняли, что называется распределенной системой и как она устроена? + +### Задание +Написать небольшое эссе (буквально несколько абзацев) своими словами (пожалуйста не пользуйтесь гуглом :) на тему "Устройство распределенных систем". + +  1. Зачем сложные системы (например, социальная сеть ВКонтакте) пишутся в "распределенном" стиле, где каждое отдельное приложение (или сервис) функционально выполняет только ограниченный спектр задач? + +  2. Для чего были созданы системы оркестрации приложений? Каким образом они упрощают / усложняют разработку и сопровождение распределенных систем? + +  3. Для чего нужны очереди обработки сообщений и что может подразумеваться под сообщениями? + +  4. Какие преимущества и недостатки распределенных приложений существуют на Ваш взгляд? + +  5. Целесообразно ли в сложную распределенную систему внедрять параллельные вычисления? Приведите примеры, когда это действительно нужно, а когда нет. + +### Эссе + +Устройство распределенных систем представляет собой сложный и многогранный процесс, призванный обеспечить эффективную работу со сложными и объемными данными. Одной из причин, по которой такие системы, например, социальная сеть ВКонтакте, организуются в распределенном стиле, является возможность более эффективного управления и обработки информации. Каждое отдельное приложение или сервис в такой системе выполняет свои ограниченные функциональные задачи, что упрощает разделение и оптимизацию работы. + +Для согласованной работы таких распределенных приложений созданы системы оркестрации, которые позволяют управлять, мониторить и масштабировать процессы работы приложений. Оркестраторы упрощают разработку и сопровождение распределенных систем, обеспечивая автоматизацию процессов и контроль за выполнением задач. + +Очереди обработки сообщений также являются важной частью распределенных систем, позволяя эффективно передавать информацию и контролировать ее обработку. Сообщения могут содержать различную информацию, от запросов на данные до результатов вычислений, обеспечивая согласованную работу различных компонентов системы. + +Преимущества распределенных приложений можно назвать возможностью масштабирования, более высокой отказоустойчивостью и распределением нагрузки. Однако существуют и недостатки, такие как сложность разработки, стоимость обслуживания и возможные проблемы с согласованностью данных. + +Внедрение параллельных вычислений в сложную распределенную систему может быть целесообразным в случаях, когда требуется обработка больших объемов данных или выполнение вычислительно сложных операций. Например, в системе анализа больших данных параллельные вычисления позволяют значительно ускорить выполнение вычислений. Однако, в некоторых случаях это может быть излишне сложно и неоправданно, например, при работе с небольшими объемами данных или простыми операциями. \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/Consumer1.py b/yakovleva_yulia_lab_4/Consumer1.py new file mode 100644 index 0000000..f11b6bf --- /dev/null +++ b/yakovleva_yulia_lab_4/Consumer1.py @@ -0,0 +1,43 @@ +import pika +import random +import time +from datetime import datetime + +queue_name = 'queue1' +exchange = 'logs' + +def callback(ch, method, properties, body): + received_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + message = body.decode() + + print(f"[{received_time}] Потребитель 1: сообщение - '{message}'") + + # Имитация обработки сообщения + time.sleep(random.choice([1, 2])) + + print(f"[{received_time}] Потребитель 1: сообщение '{message}' обработано\n") + + ch.basic_ack(delivery_tag=method.delivery_tag) + +def setup_connection(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + + channel.queue_declare(queue=queue_name) + + channel.queue_bind(exchange=exchange, queue=queue_name) + + return connection, channel + +if __name__ == '__main__': + connection, channel = setup_connection() + try: + print("[*] Ожидание сообщений") + channel.basic_consume(queue=queue_name, on_message_callback=callback) + channel.start_consuming() + except KeyboardInterrupt: + print("Остановка...") + finally: + if connection.is_open: + connection.close() + print("Соединение закрыто.") diff --git a/yakovleva_yulia_lab_4/Consumer2.py b/yakovleva_yulia_lab_4/Consumer2.py new file mode 100644 index 0000000..f3d5c71 --- /dev/null +++ b/yakovleva_yulia_lab_4/Consumer2.py @@ -0,0 +1,36 @@ +import pika +from datetime import datetime + +queue_name = 'queue2' +exchange = 'logs' + +def callback(ch, method, properties, body): + received_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + message = body.decode() + print(f"[{received_time}] Потребитель 2: пришло сообщение '{message}'") + print(f"[{received_time}] Потребитель 2: сообщение '{message}' обработано\n") + + ch.basic_ack(delivery_tag=method.delivery_tag) + +def setup_connection(): + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + + channel.queue_declare(queue=queue_name) + + channel.queue_bind(exchange=exchange, queue=queue_name) + + return connection, channel + +if __name__ == '__main__': + connection, channel = setup_connection() + try: + print("[*] Ожидание сообщений") + channel.basic_consume(queue=queue_name, on_message_callback=callback) + channel.start_consuming() + except KeyboardInterrupt: + print("Остановка...") + finally: + if connection.is_open: + connection.close() + print("Соединение закрыто.") diff --git a/yakovleva_yulia_lab_4/EmitLog/.gitignore b/yakovleva_yulia_lab_4/EmitLog/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/EmitLog/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/EmitLog/EmitLog.cs b/yakovleva_yulia_lab_4/EmitLog/EmitLog.cs new file mode 100644 index 0000000..9bf40f0 --- /dev/null +++ b/yakovleva_yulia_lab_4/EmitLog/EmitLog.cs @@ -0,0 +1,24 @@ +using System.Text; +using RabbitMQ.Client; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout); + +var message = GetMessage(args); +var body = Encoding.UTF8.GetBytes(message); +channel.BasicPublish(exchange: "logs", + routingKey: string.Empty, + basicProperties: null, + body: body); +Console.WriteLine($" [x] Sent {message}"); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); + +static string GetMessage(string[] args) +{ + return ((args.Length > 0) ? string.Join(" ", args) : "info: Hello World!"); +} \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/EmitLog/EmitLog.csproj b/yakovleva_yulia_lab_4/EmitLog/EmitLog.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/EmitLog/EmitLog.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/NewTask/.gitignore b/yakovleva_yulia_lab_4/NewTask/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/NewTask/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/NewTask/NewTask.cs b/yakovleva_yulia_lab_4/NewTask/NewTask.cs new file mode 100644 index 0000000..31f4518 --- /dev/null +++ b/yakovleva_yulia_lab_4/NewTask/NewTask.cs @@ -0,0 +1,32 @@ +using System.Text; +using RabbitMQ.Client; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.QueueDeclare(queue: "task_queue", + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); + +var message = GetMessage(args); +var body = Encoding.UTF8.GetBytes(message); + +var properties = channel.CreateBasicProperties(); +properties.Persistent = true; + +channel.BasicPublish(exchange: string.Empty, + routingKey: "task_queue", + basicProperties: properties, + body: body); +Console.WriteLine($" [x] Sent {message}"); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); + +static string GetMessage(string[] args) +{ + return ((args.Length > 0) ? string.Join(" ", args) : "Hello World!"); +} \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/NewTask/NewTask.csproj b/yakovleva_yulia_lab_4/NewTask/NewTask.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/NewTask/NewTask.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/Publisher.py b/yakovleva_yulia_lab_4/Publisher.py new file mode 100644 index 0000000..708fb46 --- /dev/null +++ b/yakovleva_yulia_lab_4/Publisher.py @@ -0,0 +1,22 @@ +import pika +import time + +if __name__ == '__main__': + connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) + channel = connection.channel() + channel.exchange_declare(exchange='logs', exchange_type='fanout') + + messages = [ + "Приехал товар", + "Клиент забронировал компьютер", + "Необходимо создать отчет за день" + ] + + try: + while True: + for message in messages: + channel.basic_publish(exchange='logs', routing_key='', body=message) + print(f"Отправлено сообщение: {message}") + time.sleep(1) # Задержка между сообщениями + except KeyboardInterrupt: + connection.close() diff --git a/yakovleva_yulia_lab_4/README.md b/yakovleva_yulia_lab_4/README.md new file mode 100644 index 0000000..0d44d44 --- /dev/null +++ b/yakovleva_yulia_lab_4/README.md @@ -0,0 +1,33 @@ +# Лабораторная работа №4 - Работа с брокером сообщений + +## Описание +Был установлен брокер сообщений RabbitMQ и выполнены 3 задачи туториала. Было разработано демонстрационное приложение работы с брокером сообщений RabbitMQ по предметной области "Управление компьютерным клубом" + +## Прохождение tutorials: + +tutorial 1 +![результат работы](./images/image1.jpg) + +tutorial 2 +![результат работы](./images/image2.jpg) + +tutorial 3 +![результат работы](./images/image3.jpg) +![результат работы](./images/image4.jpg) + + +## Демонстрация работы: + +#### При одном запущенном Consumer1 +![результат работы](./images/image5.jpg) +#### При двух запущенном Consumer1 +![изображение 2](./images/image6.jpg) +#### При трёх запущенном Consumer1 +![изображение 3](./images/image7.jpg) +#### Очередь 2 +![изображение 4](./images/image8.jpg) + +Здесь мы видим, что чем больше запущено обработчиков сообщений, тем меньше они задерживаются в очереди. Также здесь видно, что очередь 2 всегда свободна, так как Consumer2 работает без задержек и сразу обрабатывает сообщения, в отличие от Consumer1, где установлена задержка. + +## Отчет +Работоспособность: [Видео](https://vk.com/video372869030_456239956?list=ln-EaS6eqRVNMM9TB5zyE) \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/Receive/.gitignore b/yakovleva_yulia_lab_4/Receive/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/Receive/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/Receive/Receive.cs b/yakovleva_yulia_lab_4/Receive/Receive.cs new file mode 100644 index 0000000..37b2c84 --- /dev/null +++ b/yakovleva_yulia_lab_4/Receive/Receive.cs @@ -0,0 +1,29 @@ +using System.Text; +using RabbitMQ.Client; +using RabbitMQ.Client.Events; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.QueueDeclare(queue: "hello", + durable: false, + exclusive: false, + autoDelete: false, + arguments: null); + +Console.WriteLine(" [*] Waiting for messages."); + +var consumer = new EventingBasicConsumer(channel); +consumer.Received += (model, ea) => +{ + var body = ea.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + Console.WriteLine($" [x] Received {message}"); +}; +channel.BasicConsume(queue: "hello", + autoAck: true, + consumer: consumer); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/Receive/Receive.csproj b/yakovleva_yulia_lab_4/Receive/Receive.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/Receive/Receive.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/ReceiveLogs/.gitignore b/yakovleva_yulia_lab_4/ReceiveLogs/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/ReceiveLogs/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.cs b/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.cs new file mode 100644 index 0000000..2c3fc61 --- /dev/null +++ b/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.cs @@ -0,0 +1,31 @@ +using System.Text; +using RabbitMQ.Client; +using RabbitMQ.Client.Events; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout); + +// declare a server-named queue +var queueName = channel.QueueDeclare().QueueName; +channel.QueueBind(queue: queueName, + exchange: "logs", + routingKey: string.Empty); + +Console.WriteLine(" [*] Waiting for logs."); + +var consumer = new EventingBasicConsumer(channel); +consumer.Received += (model, ea) => +{ + byte[] body = ea.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + Console.WriteLine($" [x] {message}"); +}; +channel.BasicConsume(queue: queueName, + autoAck: true, + consumer: consumer); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.csproj b/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/ReceiveLogs/ReceiveLogs.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/Send/.gitignore b/yakovleva_yulia_lab_4/Send/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/Send/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/Send/Send.cs b/yakovleva_yulia_lab_4/Send/Send.cs new file mode 100644 index 0000000..86fc3ec --- /dev/null +++ b/yakovleva_yulia_lab_4/Send/Send.cs @@ -0,0 +1,24 @@ +using System.Text; +using RabbitMQ.Client; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.QueueDeclare(queue: "hello", + durable: false, + exclusive: false, + autoDelete: false, + arguments: null); + +var message = "Hello World!"; +var body = Encoding.UTF8.GetBytes(message); + +channel.BasicPublish(exchange: string.Empty, + routingKey: "hello", + basicProperties: null, + body: body); +Console.WriteLine($" [x] Sent {message}"); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/Send/Send.csproj b/yakovleva_yulia_lab_4/Send/Send.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/Send/Send.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/Worker/.gitignore b/yakovleva_yulia_lab_4/Worker/.gitignore new file mode 100644 index 0000000..5e57f18 --- /dev/null +++ b/yakovleva_yulia_lab_4/Worker/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/yakovleva_yulia_lab_4/Worker/Worker.cs b/yakovleva_yulia_lab_4/Worker/Worker.cs new file mode 100644 index 0000000..e712fba --- /dev/null +++ b/yakovleva_yulia_lab_4/Worker/Worker.cs @@ -0,0 +1,39 @@ +using System.Text; +using RabbitMQ.Client; +using RabbitMQ.Client.Events; + +var factory = new ConnectionFactory { HostName = "localhost" }; +using var connection = factory.CreateConnection(); +using var channel = connection.CreateModel(); + +channel.QueueDeclare(queue: "task_queue", + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); + +channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); + +Console.WriteLine(" [*] Waiting for messages."); + +var consumer = new EventingBasicConsumer(channel); +consumer.Received += (model, ea) => +{ + byte[] body = ea.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + Console.WriteLine($" [x] Received {message}"); + + int dots = message.Split('.').Length - 1; + Thread.Sleep(dots * 1000); + + Console.WriteLine(" [x] Done"); + + // here channel could also be accessed as ((EventingBasicConsumer)sender).Model + channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); +}; +channel.BasicConsume(queue: "task_queue", + autoAck: false, + consumer: consumer); + +Console.WriteLine(" Press [enter] to exit."); +Console.ReadLine(); \ No newline at end of file diff --git a/yakovleva_yulia_lab_4/Worker/Worker.csproj b/yakovleva_yulia_lab_4/Worker/Worker.csproj new file mode 100644 index 0000000..844ba8f --- /dev/null +++ b/yakovleva_yulia_lab_4/Worker/Worker.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/yakovleva_yulia_lab_4/images/image1.jpg b/yakovleva_yulia_lab_4/images/image1.jpg new file mode 100644 index 0000000..77e839c Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image1.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image2.jpg b/yakovleva_yulia_lab_4/images/image2.jpg new file mode 100644 index 0000000..b5710c2 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image2.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image3.jpg b/yakovleva_yulia_lab_4/images/image3.jpg new file mode 100644 index 0000000..134081f Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image3.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image4.jpg b/yakovleva_yulia_lab_4/images/image4.jpg new file mode 100644 index 0000000..004a6e9 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image4.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image5.jpg b/yakovleva_yulia_lab_4/images/image5.jpg new file mode 100644 index 0000000..cfeb6c9 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image5.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image6.jpg b/yakovleva_yulia_lab_4/images/image6.jpg new file mode 100644 index 0000000..de494f6 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image6.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image7.jpg b/yakovleva_yulia_lab_4/images/image7.jpg new file mode 100644 index 0000000..1ad5445 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image7.jpg differ diff --git a/yakovleva_yulia_lab_4/images/image8.jpg b/yakovleva_yulia_lab_4/images/image8.jpg new file mode 100644 index 0000000..14e57e2 Binary files /dev/null and b/yakovleva_yulia_lab_4/images/image8.jpg differ diff --git a/zhimolostnova_anna_lab_5/README.md b/zhimolostnova_anna_lab_5/README.md new file mode 100644 index 0000000..ed266a5 --- /dev/null +++ b/zhimolostnova_anna_lab_5/README.md @@ -0,0 +1,75 @@ +# Отчет по лабораторной работе №5 + +## Описание задачи + +В лабораторной работе необходимо реализовать два алгоритма для умножения квадратных матриц: +последовательный и параллельный. Параллельный алгоритм должен поддерживать настройку количества потоков, +что позволит гибко распределять нагрузку. Бенчмарки проводились на матрицах размером 100x100, 300x300 +и 500x500 для анализа производительности каждого алгоритма. + +## Структура проекта + +Проект состоит из двух файлов с реализацией алгоритмов: + +- regular.go — реализация последовательного умножения матриц. +- parallel.go — реализация параллельного умножения матриц с заданным количеством потоков. +- matrix.go (в папке util) — вспомогательные функции для создания матриц. + +## Результаты + +### Последовательное умножение + +![img_1.png](images%2Fimg_1.png) + +| Размер матрицы | Время выполнения | +|-----------------|------------------| +| 100x100 | 2.1442ms | +| 300x300 | 59.4206ms | +| 500x500 | 382.7277ms | + +### Параллельное умножение + +![img.png](images%2Fimg.png) + +| Размер матрицы | Количество потоков | Время выполнения | +|----------------|--------------------|------------------| +| 100x100 | 2 | 1.1137ms | +| 100x100 | 4 | 524.1µs | +| 100x100 | 6 | 546.2µs | +| 100x100 | 8 | 527.6µs | +| 300x300 | 2 | 41.6503ms | +| 300x300 | 4 | 25.7563ms | +| 300x300 | 6 | 19.4356ms | +| 300x300 | 8 | 15.0006ms | +| 500x500 | 2 | 216.1878ms | +| 500x500 | 4 | 119.4361ms | +| 500x500 | 6 | 98.5036ms | +| 500x500 | 8 | 76.9725ms | + +## Анализ полученных данных + +1. Последовательное умножение: + - Время выполнения линейно увеличивается с ростом размера матрицы. Это связано с тем, + что алгоритм работает с комплексностью O(n³), где n — размер матрицы. + - Для больших матриц (500x500) время выполнения становится заметно больше, что подчеркивает + ограниченность этого метода при работе с большими объемами данных. +2. Параллельное умножение: + - Параллельный алгоритм показал значительное улучшение времени выполнения по сравнению с + последовательным, особенно при увеличении количества потоков. + - Например, для матриц 100x100 время выполнения снизилось с 1.6ms до 524.1µs при использовании + 4 потоков. + - Для матриц большего размера (500x500) прирост производительности также существенный: + с 393.65ms (последовательное умножение) до 76.97ms при 8 потоках. + - Однако, начиная с 6 потоков, улучшения становятся менее значительными. Это связано с накладными + расходами на синхронизацию потоков и передачу данных между ними. При небольших размерах матриц такие накладные расходы могут нивелировать прирост производительности. +3. Заключение: + - Параллельный алгоритм значительно превосходит последовательный при увеличении размера + матриц и количества потоков. Однако для небольших матриц с увеличением количества потоков, прирост + производительности не всегда оправдан из-за накладных расходов на управление потоками. + - Оптимальное количество потоков зависит от размера матриц: для небольших матриц 4 потока дают + значительное улучшение, а для матриц большего размера (500x500) лучше использовать 8 потоков для + максимальной эффективности. + +## Демонстрационное видео + +Видеозапись доступна по адресу: [https://vk.com/video193898050_456240873](https://vk.com/video193898050_456240873) \ No newline at end of file diff --git a/zhimolostnova_anna_lab_5/images/img.png b/zhimolostnova_anna_lab_5/images/img.png new file mode 100644 index 0000000..96221f4 Binary files /dev/null and b/zhimolostnova_anna_lab_5/images/img.png differ diff --git a/zhimolostnova_anna_lab_5/images/img_1.png b/zhimolostnova_anna_lab_5/images/img_1.png new file mode 100644 index 0000000..b8a44e5 Binary files /dev/null and b/zhimolostnova_anna_lab_5/images/img_1.png differ diff --git a/zhimolostnova_anna_lab_5/parallel.go b/zhimolostnova_anna_lab_5/parallel.go new file mode 100644 index 0000000..715ccff --- /dev/null +++ b/zhimolostnova_anna_lab_5/parallel.go @@ -0,0 +1,72 @@ +package main + +import ( + "fmt" + "strconv" + "sync" + "time" + "zhimolostnova_anna_lab_5/util" +) + +// Параллельное умножение матриц +func multiplyMatricesParallel(a, b [][]int, threads int) [][]int { + size := len(a) + result := make([][]int, size) + for i := range result { + result[i] = make([]int, size) + } + + // Функция для обработки части работы потока + worker := func(startRow, endRow int, wg *sync.WaitGroup) { + defer wg.Done() + for i := startRow; i < endRow; i++ { + for j := 0; j < size; j++ { + for k := 0; k < size; k++ { + result[i][j] += a[i][k] * b[k][j] + } + } + } + } + + // Запуск потоков + var wg sync.WaitGroup + rowsPerThread := size / threads + for i := 0; i < threads; i++ { + startRow := i * rowsPerThread + endRow := startRow + rowsPerThread + if i == threads-1 { + endRow = size + } + wg.Add(1) + go worker(startRow, endRow, &wg) + } + + wg.Wait() + return result +} + +func benchmarkMatrixMultiplication(sizes []int, threadsList []int) { + for _, size := range sizes { + for _, threads := range threadsList { + matrixA := util.CreateMatrix(size) + matrixB := util.CreateMatrix(size) + + start := time.Now() + _ = multiplyMatricesParallel(matrixA, matrixB, threads) + elapsed := time.Since(start) + + fmt.Printf("Parallel multiplication of matrix %sx%s with %d threads took %s\n", strconv.Itoa(size), strconv.Itoa(size), threads, elapsed) + } + } +} + +func main() { + // Список размерностей матриц + sizes := []int{100, 300, 500} + + // Список количества потоков для тестирования + threadsList := []int{2, 4, 6, 8} + + // Запуск бенчмарка + benchmarkMatrixMultiplication(sizes, threadsList) +} diff --git a/zhimolostnova_anna_lab_5/regular.go b/zhimolostnova_anna_lab_5/regular.go new file mode 100644 index 0000000..2a4d43b --- /dev/null +++ b/zhimolostnova_anna_lab_5/regular.go @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + "strconv" + "time" + "zhimolostnova_anna_lab_5/util" +) + +// Последовательное умножение двух квадратных матриц +func multiplyMatricesSequential(a, b [][]int) [][]int { + size := len(a) + result := make([][]int, size) + for i := range result { + result[i] = make([]int, size) + for j := 0; j < size; j++ { + for k := 0; k < size; k++ { + result[i][j] += a[i][k] * b[k][j] + } + } + } + return result +} + +// Функция для бенчмарка последовательного умножения +func benchmarkMatrixMultiplicationSequential(sizes []int) { + for _, size := range sizes { + matrixA := util.CreateMatrix(size) + matrixB := util.CreateMatrix(size) + + start := time.Now() + _ = multiplyMatricesSequential(matrixA, matrixB) + elapsed := time.Since(start) + + fmt.Printf("Sequential multiplication of matrix %sx%s took %s\n", strconv.Itoa(size), strconv.Itoa(size), elapsed) + } +} + +func main() { + // Список размерностей матриц + sizes := []int{100, 300, 500} + + // Запуск бенчмарка + benchmarkMatrixMultiplicationSequential(sizes) +} diff --git a/zhimolostnova_anna_lab_5/util/matrix.go b/zhimolostnova_anna_lab_5/util/matrix.go new file mode 100644 index 0000000..5162b41 --- /dev/null +++ b/zhimolostnova_anna_lab_5/util/matrix.go @@ -0,0 +1,17 @@ +package util + +import ( + "math/rand" +) + +// CreateMatrix Функция для создания квадратной матрицы заданного размера +func CreateMatrix(size int) [][]int { + matrix := make([][]int, size) + for i := range matrix { + matrix[i] = make([]int, size) + for j := range matrix[i] { + matrix[i][j] = rand.Intn(25) // Заполняем случайными числами от 0 до 25 + } + } + return matrix +} diff --git a/zhimolostnova_anna_lab_6/README.md b/zhimolostnova_anna_lab_6/README.md new file mode 100644 index 0000000..7b7cdd9 --- /dev/null +++ b/zhimolostnova_anna_lab_6/README.md @@ -0,0 +1,87 @@ +# Отчет по лабораторной работе №6 + +## Описание задачи + +Данная работа нацелена на изучение эффективности параллельных вычислений при нахождении детерминанта +квадратной матрицы. Были реализованы два алгоритма: + +1. **Последовательный алгоритм**: рекурсивное вычисление детерминанта методом разложения по строкам. +2. **Параллельный алгоритм**: вычисление детерминанта с использованием многопоточности, + где различные миноры матрицы вычисляются в отдельных потоках. + +Целью эксперимента было сравнение времени выполнения последовательного и параллельного алгоритмов для +матриц разного размера и с разным количеством потоков. + +## Структура проекта + +Проект состоит из двух файлов с реализацией алгоритмов: + +- regular.go (в папке alg) — рекурсивное вычисление детерминанта методом разложения по строкам. +- parallel.go (в папке alg) — вычисление детерминанта с использованием многопоточности, + где различные миноры матрицы вычисляются в отдельных потоках. +- matrix.go (в папке util) — вспомогательные функции для матриц. +- run.go - запуск бенчмарков. + +## Результаты + +### Последовательный алгоритм + +![img.png](images%2Fimg.png) + +| Размер матрицы | Время выполнения | +|----------------|------------------| +| 7x7 | 525.1µs | +| 8x8 | 5.8494ms | +| 9x9 | 35.3115ms | + +### Параллельный алгоритм + +![img_1.png](images%2Fimg_1.png) + +| Размер матрицы | Количество потоков | Время выполнения | +|----------------|--------------------|------------------| +| 7x7 | 2 | 2ms | +| 7x7 | 4 | 2.0009ms | +| 7x7 | 6 | 1.0002ms | +| 7x7 | 8 | 1.9989ms | +| 8x8 | 2 | 5.0014ms | +| 8x8 | 4 | 21.5145ms | +| 8x8 | 6 | 16.3851ms | +| 8x8 | 8 | 17.9676ms | +| 9x9 | 2 | 65.099ms | +| 9x9 | 4 | 115.9553ms | +| 9x9 | 6 | 161.408ms | +| 9x9 | 8 | 117.4747ms | + +## Анализ полученных данных + +1. **Последовательный алгоритм**: + + Последовательный алгоритм показал ожидаемую тенденцию: с увеличением размера матрицы, время выполнения + увеличивается экспоненциально. Это связано с тем, что сложность рекурсивного алгоритма вычисления + детерминанта составляет O(n!), где n — размер матрицы. Даже небольшое увеличение размера матрицы + приводит к значительному росту времени вычислений. +2. **Параллельный алгоритм**: + + **Матрицы 7x7**: + - Время параллельного алгоритма оказалось больше, чем последовательного. + Это связано с тем, что накладные расходы на создание потоков, синхронизацию данных и распределение + задач превышают выгоду от параллельного выполнения для небольших задач. Матрица 7x7 слишком мала, + чтобы эффективно распределить вычисления между потоками, поэтому многопоточность не дает прироста в + производительности. + + **Матрицы 8x8**: + - Параллельное вычисление снова оказалось медленнее последовательного. Время выполнения с увеличением + количества потоков увеличивалось вплоть до 4 потоков, что демонстрирует отрицательный эффект от + создания избыточного числа потоков для задач такого размера. Наибольшее ускорение удалось достичь с 2 и 6 потоками, + но даже в этом случае результат (5.0014 и 16.3851 ms) был хуже и менее стабильным последовательного (5.8494 ms). + + **Матрицы 9x9**: + - Здесь также наблюдается значительное замедление при увеличении количества потоков. Время с 8 потоками + составило 117.4747 ms, что все равно больше времени последовательного алгоритма (35.3115 ms). Это связано с тем, + что при увеличении числа потоков на задаче, где каждая операция по вычислению минора требует больших + вычислительных затрат, накладные расходы на управление потоками могут стать слишком велики. + +## Демонстрационное видео + +Видеозапись доступна по адресу: [https://vk.com/video193898050_456240874](https://vk.com/video193898050_456240874) \ No newline at end of file diff --git a/zhimolostnova_anna_lab_6/alg/parallel.go b/zhimolostnova_anna_lab_6/alg/parallel.go new file mode 100644 index 0000000..1987928 --- /dev/null +++ b/zhimolostnova_anna_lab_6/alg/parallel.go @@ -0,0 +1,47 @@ +package alg + +import ( + "sync" + "zhimolostnova_anna_lab_6/util" +) + +func DeterminantParallel(matrix [][]float64, workers int) float64 { + size := len(matrix) + + if size == 1 { + return matrix[0][0] + } + + if size == 2 { + return matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0] + } + + det := 0.0 + wg := sync.WaitGroup{} + mu := sync.Mutex{} + chunks := size / workers + if chunks == 0 { + chunks = 1 + } + for j := 0; j < size; j += chunks { + wg.Add(1) + go func(jStart int) { + defer wg.Done() + localDet := 0.0 + for jj := jStart; jj < jStart+chunks && jj < size; jj++ { + subMatrix := util.GetMinor(matrix, jj) + sign := 1 + if jj%2 != 0 { + sign = -1 + } + localDet += float64(sign) * matrix[0][jj] * DeterminantParallel(subMatrix, workers) + } + mu.Lock() + det += localDet + mu.Unlock() + }(j) + } + + wg.Wait() + return det +} diff --git a/zhimolostnova_anna_lab_6/alg/regular.go b/zhimolostnova_anna_lab_6/alg/regular.go new file mode 100644 index 0000000..eec7134 --- /dev/null +++ b/zhimolostnova_anna_lab_6/alg/regular.go @@ -0,0 +1,30 @@ +package alg + +import ( + "zhimolostnova_anna_lab_6/util" +) + +// Determinant Функция для вычисления детерминанта матрицы +func Determinant(matrix [][]float64) float64 { + size := len(matrix) + + if size == 1 { + return matrix[0][0] + } + + if size == 2 { + return matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0] + } + + // Рекурсивное вычисление детерминанта по разложению по первой строке + det := 0.0 + for j := 0; j < size; j++ { + subMatrix := util.GetMinor(matrix, j) + sign := 1 + if j%2 != 0 { + sign = -1 + } + det += float64(sign) * matrix[0][j] * Determinant(subMatrix) + } + return det +} diff --git a/zhimolostnova_anna_lab_6/images/img.png b/zhimolostnova_anna_lab_6/images/img.png new file mode 100644 index 0000000..e3ac208 Binary files /dev/null and b/zhimolostnova_anna_lab_6/images/img.png differ diff --git a/zhimolostnova_anna_lab_6/images/img_1.png b/zhimolostnova_anna_lab_6/images/img_1.png new file mode 100644 index 0000000..0be77ae Binary files /dev/null and b/zhimolostnova_anna_lab_6/images/img_1.png differ diff --git a/zhimolostnova_anna_lab_6/run.go b/zhimolostnova_anna_lab_6/run.go new file mode 100644 index 0000000..fcc1604 --- /dev/null +++ b/zhimolostnova_anna_lab_6/run.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "strconv" + "time" + "zhimolostnova_anna_lab_6/alg" + "zhimolostnova_anna_lab_6/util" +) + +// Функция для бенчмарка последовательного вычисления детерминанта +func benchmarkDeterminantSequential(sizes []int) { + for _, size := range sizes { + matrix := util.GenerateMatrix(size) + + start := time.Now() + _ = alg.Determinant(matrix) + elapsed := time.Since(start) + + fmt.Printf("Sequential determinant of matrix %sx%s took %s\n", strconv.Itoa(size), strconv.Itoa(size), elapsed) + } +} + +// Функция для бенчмарка параллельного вычисления детерминанта +func benchmarkDeterminantParallel(sizes []int, threadsList []int) { + for _, size := range sizes { + for _, threads := range threadsList { + matrix := util.GenerateMatrix(size) + + start := time.Now() + _ = alg.DeterminantParallel(matrix, threads) + elapsed := time.Since(start) + + fmt.Printf("Parallel determinant of matrix %sx%s with %d threads took %s\n", strconv.Itoa(size), strconv.Itoa(size), threads, elapsed) + } + } +} + +func main() { + // Список размерностей матриц + sizes := []int{7, 8, 9} + + // Список количества потоков для тестирования + threadsList := []int{2, 4, 6, 8} + + // Запуск бенчмарков + fmt.Println("Sequential Benchmark:") + benchmarkDeterminantSequential(sizes) + + fmt.Println("\nParallel Benchmark:") + benchmarkDeterminantParallel(sizes, threadsList) +} diff --git a/zhimolostnova_anna_lab_6/util/matrix.go b/zhimolostnova_anna_lab_6/util/matrix.go new file mode 100644 index 0000000..b9430c7 --- /dev/null +++ b/zhimolostnova_anna_lab_6/util/matrix.go @@ -0,0 +1,36 @@ +package util + +import "math/rand" + +// GetMinor Получение минора матрицы +func GetMinor(matrix [][]float64, col int) [][]float64 { + size := len(matrix) + minor := make([][]float64, size-1) + for i := range minor { + minor[i] = make([]float64, size-1) + } + + for i := 1; i < size; i++ { + subCol := 0 + for j := 0; j < size; j++ { + if j == col { + continue + } + minor[i-1][subCol] = matrix[i][j] + subCol++ + } + } + return minor +} + +// GenerateMatrix Генерация случайной матрицы размера size x size +func GenerateMatrix(size int) [][]float64 { + matrix := make([][]float64, size) + for i := range matrix { + matrix[i] = make([]float64, size) + for j := range matrix[i] { + matrix[i][j] = float64(rand.Intn(6)) + } + } + return matrix +} diff --git a/zhimolostnova_anna_lab_7/README.md b/zhimolostnova_anna_lab_7/README.md new file mode 100644 index 0000000..85f75c4 --- /dev/null +++ b/zhimolostnova_anna_lab_7/README.md @@ -0,0 +1,49 @@ +# Отчет по лабораторной работе №7 + +## Задание: + +Написать небольшое эссе (буквально несколько абзацев) своими словами. + +1. Какие алгоритмы и методы используются для балансировки нагрузки? +2. Какие открытые технологии существуют для балансировки нагрузки? +3. Как осуществляется балансировка нагрузки на базах данных? +4. Реверс-прокси как один из элементов балансировки нагрузки. + +## Эссе на тему: "Балансировка нагрузки в распределённых системах при помощи открытых технологий" + +Чтобы распределить входящие запросы между несколькими серверами для обеспечения равномерного +использования ресурсов и предотвращения перегрузок, существует множество алгоритмов, справляющихся +с балансировкой нагрузки, в зависимости от специфики системы и требований к производительности. +В данном случае будет рассмотрено 3 самых популярных алгоритма. + +К примеру, Round Robin и Weighted Round Robin. Оба алгоритма являются циклическими и поочередно +распределяют запросы между серверами. Однако в отличие от обычного Round Robin, Weighted Round Robin +учитывает мощность серверов, поэтому серверы с большей производительностью получают большее +количество запросов. + +С наименьшим количество отброшенных запросов работает алгоритм Least Connections, суть которого заключается +в том, что сначала отправляются запросы серверу с наименьшим количеством активных подключений. Это помогает +равномерно распределять нагрузку в реальном времени. + +Чтобы реализовать балансировку нагрузки, можно обратиться к NGINX. Он широко известен как веб-сервер, +но также может быть использован для балансировки нагрузки на уровне приложений и HTTP-запросов. Остаётся +универсальным решением с хорошей производительностью и гибкостью, но его придётся настраивать вручную в +некоторых сценариях, где HAProxy и Traefik предоставляют автоматизированные и специализированные решения. + +Для высокопроизводительных и масштабируемых систем, требующих тонкого управления на уровне TCP и HTTP лучше +выбрать HAProxy, а Traefik идеально подходит для современных облачных архитектур и микросервисов благодаря +автоматическому обнаружению и динамической конфигурации. + +Что же касается баз данных, то балансировка нагрузки на них может осуществляться на нескольких уровнях: +уровне чтения, записи или репликации. Например, в системах с репликацией данных (как в MySQL) запросы на +чтение могут направляться на реплики, а на запись – только на мастер-узел. Это позволяет снизить нагрузку +на основной сервер базы данных и увеличить производительность системы. + +Упомянутые выше Traefik, HAProxy и NGINX являются также реверс-прокси, обеспечивая балансировку на +уровне HTTP или TCP. Реверс-прокси – это сервер, который принимает запросы от клиентов и перенаправляет +их на внутренние серверы. Он может использоваться для балансировки нагрузки, распределяя запросы между +несколькими серверами в зависимости от состояния системы и доступности ресурсов. + +Подводя итог, балансировка нагрузки это необходимый элемент для построения надёжных и +масштабируемых распределённых систем, а использование современных открытых технологий помогает эффективно +распределять запросы между серверами, улучшая производительность систем. \ No newline at end of file diff --git a/zhimolostnova_anna_lab_8/README.md b/zhimolostnova_anna_lab_8/README.md new file mode 100644 index 0000000..e2ff0e7 --- /dev/null +++ b/zhimolostnova_anna_lab_8/README.md @@ -0,0 +1,63 @@ +# Отчет по лабораторной работе №8 + +## Задание: + +Написать небольшое эссе (буквально несколько абзацев) своими словами на тему "Устройство распределенных +систем". А помогут Вам в этом вопросы из списка: + +1. Зачем сложные системы (например, социальная сеть ВКонтакте) пишутся в "распределенном" стиле, где + каждое отдельное приложение (или сервис) функционально выполняет только ограниченный спектр задач? +2. Для чего были созданы системы оркестрации приложений? Каким образом они упрощают / усложняют + разработку и сопровождение распределенных систем? +3. Для чего нужны очереди обработки сообщений и что может подразумеваться под сообщениями? +4. Какие преимущества и недостатки распределенных приложений существуют на Ваш взгляд? +5. Целесообразно ли в сложную распределенную систему внедрять параллельные вычисления? Приведите примеры, + когда это действительно нужно, а когда нет. + +## Эссе на тему: "Устройство распределенных систем" + +Как было рассмотрено ранее на лекциях, распределённые системы – это архитектура, в которой компоненты +приложения работают на разных серверах и взаимодействуют друг с другом через сеть. В такой системе +есть разные сервисы отвечают за конкретные задачи. К примеру, один отвечает за обработку сообщений, +другой – за управление пользователями, третий – за работу с медиафайлами. + +Однако почему используется именно этот подход? Основная причина заключается в масштабируемости и надёжности +подобных систем. Когда каждая функциональная часть системы – это отдельный сервис, можно +легко масштабировать только ту часть, которая испытывает большую нагрузку. К примеру, если в системе +возрастает количество запросов на загрузку фото, можно увеличить количество серверов, обрабатывающих +изображения, не затрагивая при этом другие сервисы. Еще одно важное преимущество распределённой системы: +если один сервис выйдет из строя, остальные продолжат работать. + +Управление подобными системами требует от разработчика знание механизма оркестрации. Системы оркестрации, +такие, как Kubernetes, были созданы для управления и автоматизации развертывания, масштабирования и +поддержки приложений, состоящих из множества микросервисов. Данный механизм упрощает разработку и +сопровождение распределённых приложений, позволяя автоматизировать задачи, такие как восстановление при +сбоях, обновление сервисов и распределение нагрузки. Несомненно, использование оркестраторов усложнит +начальную настройку и обучение, так как потребует глубокого понимания инфраструктуры и сетевой безопасности. + +Еще одна технология, которой необходимо владеть прежде чем приступить к работе с распределенными системами, +это обработка сообщений. Она имеет очереди обработки сообщений – инструмент для асинхронной коммуникации +между различными компонентами системы. Под "сообщениями" могут подразумеваться данные или задачи, которые +один сервис отправляет другому для обработки. Очереди помогают разгрузить систему, позволяя сервисам не +ожидать немедленного ответа. Например, при загрузке фото сервис, принимающий файл, может поместить задачу +обработки изображения в очередь, а другой сервис обработает её позже. Это повышает надёжность и упрощает +управление пиковыми нагрузками. + +Рассмотрев основные аспекты распределенных систем, можно выявить как негативные, так и позитивные черты. +К преимуществам распределённых систем можно отнести гибкость, масштабируемость, отказоустойчивость и +возможность использования разных технологий для каждого сервиса. Однако такие системы сложны в разработке +и сопровождении. Появляются проблемы с координацией между сервисами, отладкой, сетевой задержкой и +безопасностью данных. Балансировка этих недостатков является ключевым вызовом для распределённых систем. + +Что же касается параллельных вычислений, то их целесообразно использовать в системах с большими объёмами +данных или задачами, которые могут быть обработаны одновременно. В этом помогли убедиться 5 и 6 +лабораторные работы, где собиралась временная метрика и по которой были сделаны аналогичные выводы. +В системах машинного обучения или анализе больших данных параллельная обработка данных позволяет +существенно ускорить выполнение задач. Однако в некоторых сценариях это может быть излишним, особенно если +система работает с небольшими объёмами данных или требует строгой последовательности действий, где +параллелизм может только усложнить реализацию. + +Таким образом, можно сделать следующий вывод: распределённые системы предоставляют большие возможности для +масштабирования и надёжности, но требуют тщательного планирования и грамотного управления. Оркестрация, +очереди сообщений и параллельные вычисления являются важными инструментами, которые помогают решать задачи +таких систем, однако их использование должно быть оправдано потребностями проекта. \ No newline at end of file