diff --git a/alexandrov_dmitrii_lab_3/docker-compose.yml b/alexandrov_dmitrii_lab_3/docker-compose.yml new file mode 100644 index 0000000..8dda46b --- /dev/null +++ b/alexandrov_dmitrii_lab_3/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' +services: + usr_service: + build: + context: /user_service + dockerfile: Dockerfile + depends_on: + - msg_service + expose: + - 8082 + + msg_service: + build: + context: /message_service + dockerfile: Dockerfile + expose: + - 8081 + + nginx: + image: nginx + ports: + - 8086:8086 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - msg_service + - usr_service \ No newline at end of file diff --git a/alexandrov_dmitrii_lab_3/message_service/Dockerfile b/alexandrov_dmitrii_lab_3/message_service/Dockerfile new file mode 100644 index 0000000..cb84cf1 --- /dev/null +++ b/alexandrov_dmitrii_lab_3/message_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 + +EXPOSE 8081 + +RUN pip install Flask requests + +WORKDIR /work + +COPY msg_service.py ./ + +CMD ["python", "msg_service.py"] \ No newline at end of file diff --git a/alexandrov_dmitrii_lab_3/message_service/msg_service.py b/alexandrov_dmitrii_lab_3/message_service/msg_service.py new file mode 100644 index 0000000..15358e6 --- /dev/null +++ b/alexandrov_dmitrii_lab_3/message_service/msg_service.py @@ -0,0 +1,50 @@ +from flask import Flask, jsonify, request, Response +from datetime import datetime + +app = Flask(__name__) + +msgs = {0: {'id': 0, 'from': 0, 'to': 1, 'body': 'qq', 'dt': datetime(2023, 12, 22, 8, 0)}, + 1: {'id': 1, 'from': 1, 'to': 0, 'body': 'qq', 'dt': datetime(2023, 12, 22, 8, 5)}, + 2: {'id': 2, 'from': 0, 'to': 1, 'body': 'bye', 'dt': datetime(2023, 12, 22, 8, 10)}, + 3: {'id': 3, 'from': 1, 'to': 1, 'body': 'bye', 'dt': datetime(2023, 12, 22, 8, 15)}} + + +@app.route('/', methods=['GET', 'POST']) +def get_all(): + if request.method == 'POST': + dto = request.get_json()['dto'] + new_id = max(msgs.keys()) + 1 + msgs[new_id] = { + 'id': new_id, + 'from': dto['from'], + 'to': dto['to'], + 'body': dto['body'], + 'dt': datetime.now() + } + return jsonify(msgs[new_id]) + return jsonify(msgs) + + +@app.route('/', methods=['GET', 'PUT', 'DELETE']) +def get_by_id(msg_id): + if msg_id not in msgs.keys(): + return Response(status=404) + + if request.method == 'PUT': + dto = request.get_json()['dto'] + msgs[msg_id] = { + 'from': dto['from'], + 'to': dto['to'], + 'body': dto['body'], + 'dt': datetime.now() + } + return msgs[msg_id] + elif request.method == 'DELETE': + msgs.pop(msg_id) + return Response(status=200) + + return jsonify(msgs[msg_id]) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8081) diff --git a/alexandrov_dmitrii_lab_3/nginx.conf b/alexandrov_dmitrii_lab_3/nginx.conf new file mode 100644 index 0000000..a80bcce --- /dev/null +++ b/alexandrov_dmitrii_lab_3/nginx.conf @@ -0,0 +1,27 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 8086; + listen [::]:8086; + server_name localhost; + + location /msg_service/ { + proxy_pass http://msg_service:8081/; + 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 /usr_service/ { + proxy_pass http://usr_service:8082/; + 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/alexandrov_dmitrii_lab_3/readme.md b/alexandrov_dmitrii_lab_3/readme.md new file mode 100644 index 0000000..0bea554 --- /dev/null +++ b/alexandrov_dmitrii_lab_3/readme.md @@ -0,0 +1,32 @@ +## Задание + +1. Создать 2 микросервиса, реализующих CRUD на связанных сущностях. +2. Реализовать механизм синхронного обмена сообщениями между микросервисами. +3. Реализовать шлюз на основе прозрачного прокси-сервера nginx. + +Вариант: сообщения и пользователи + +## Выполнение +Были написаны два сервиса на языке python с технологией flask: +* Сервис msg_service, хранящий данные о сообщениях и реализующий CRUD операции с ними через HTTP запросы. +* Сервис usr_service, хранящий данные о пользователях и реализующий CRUD операции с ними через HTTP запросы. + +Сервисы синхронно сообщены - сервис пользователей запрашивает данные у сервиса сообщений для получения сообщений пользователя. + +Для сервисов прописаны файлы Dockerfile, описывающие создание контейнеров: +* Для обоих контейнеров выбирается Python 3.9. +* Оба контейнера проявляют порты, на которых работает приложение: 8081 для сообщений и 8082 для пользователей. +* В оба контейнера устанавливаются пакеты Flask и requests. +* Выбирается рабочая директория /work и туда копируются файлы скриптов. +* Командой запускаются сами скрипты. + +Общий yaml-файл развёртки был настроен следующим образом: +* блок services, где перечислены разворачиваемые сервисы. +* для каждого сервиса прописан build, где объявляется его папка и докерфайл создания и зависимости. +* для сервиса nginx прописан порт для отображения вовне. + +## Результат +Демонстрация работы в видео. + +## Ссылка на видео +https://drive.google.com/file/d/1gmZsbzMmC34Uidi4u_D3nFyPAG0MuPAf/view?usp=drive_link \ No newline at end of file diff --git a/alexandrov_dmitrii_lab_3/user_service/Dockerfile b/alexandrov_dmitrii_lab_3/user_service/Dockerfile new file mode 100644 index 0000000..8695ce6 --- /dev/null +++ b/alexandrov_dmitrii_lab_3/user_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 + +EXPOSE 8082 + +RUN pip install Flask requests + +WORKDIR /work + +COPY usr_service.py ./ + +CMD ["python", "usr_service.py"] \ No newline at end of file diff --git a/alexandrov_dmitrii_lab_3/user_service/usr_service.py b/alexandrov_dmitrii_lab_3/user_service/usr_service.py new file mode 100644 index 0000000..32a7b59 --- /dev/null +++ b/alexandrov_dmitrii_lab_3/user_service/usr_service.py @@ -0,0 +1,56 @@ +import requests +from flask import Flask, jsonify, request, Response + +app = Flask(__name__) + +usrs = {0: {'id': 0, 'name': 'anton', 'role': 'admin', 'online': False, 'msgs_sent': [0, 2], 'msgs_got': [1, 3]}, + 1: {'id': 1, 'name': 'lioha', 'role': 'user', 'online': False, 'msgs_sent': [1, 3], 'msgs_got': [0, 2]}} + + +@app.route('/', methods=['GET', 'POST']) +def get_all(): + if request.method == 'POST': + dto = request.get_json()['dto'] + new_id = max(usrs.keys()) + 1 + usrs[new_id] = { + 'id': new_id, + 'name': dto['name'], + 'role': dto['role'], + 'online': dto['online'] + } + return jsonify(usrs[new_id]) + return jsonify(usrs) + + +@app.route('/', methods=['GET', 'PUT', 'DELETE']) +def get_by_id(usr_id): + if usr_id not in usrs.keys(): + return Response(status=404) + + if request.method == 'PUT': + dto = request.get_json()['dto'] + usrs[usr_id] = { + 'name': dto['name'], + 'role': dto['role'], + 'online': dto['online'] + } + return usrs[usr_id] + elif request.method == 'DELETE': + usrs.pop(usr_id) + return Response(status=200) + + usr = usrs[usr_id] + msgs = [] + for msg_id in usr['msgs_sent']: + msgs.append(requests.get("http://msg_service:8081/"+str(msg_id)).json()) + usr['msgs_sent'] = msgs + msgs.clear() + for msg_id in usr['msgs_got']: + msgs.append(requests.get("http://msg_service:8081/"+str(msg_id)).json()) + usr['msgs_got'] = msgs + + return jsonify(usr) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8082)