diff --git a/presnyakova_victoria_lab_3/docker-compose.yml b/presnyakova_victoria_lab_3/docker-compose.yml new file mode 100644 index 0000000..20a10c6 --- /dev/null +++ b/presnyakova_victoria_lab_3/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' +services: + event_service: + build: + context: /event_service + dockerfile: Dockerfile + depends_on: + - session_service + expose: + - 8081 + + session_service: + build: + context: /session_service + dockerfile: Dockerfile + expose: + - 8082 + + nginx: + image: nginx + ports: + - 8086:8086 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - event_service + - session_service diff --git a/presnyakova_victoria_lab_3/event_service/Dockerfile b/presnyakova_victoria_lab_3/event_service/Dockerfile new file mode 100644 index 0000000..b976e86 --- /dev/null +++ b/presnyakova_victoria_lab_3/event_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 + +EXPOSE 8081 + +RUN pip install Flask requests + +WORKDIR /work + +COPY event_service.py ./ + +CMD ["python", "event_service.py"] diff --git a/presnyakova_victoria_lab_3/event_service/event_service.py b/presnyakova_victoria_lab_3/event_service/event_service.py new file mode 100644 index 0000000..59acef7 --- /dev/null +++ b/presnyakova_victoria_lab_3/event_service/event_service.py @@ -0,0 +1,48 @@ +from flask import Flask, jsonify, request, Response +from datetime import datetime + +app = Flask(__name__) + +events = {0: {'id': 0, 'session': 0, 'info': '{"defects": 1}', 'dt': datetime(2024, 10, 10, 8, 0)}, + 1: {'id': 1, 'session': 1, 'info': '{"defects": 1}', 'dt': datetime(2024, 10, 10, 8, 5)}, + 2: {'id': 2, 'session': 0, 'info': '{"defects": 1}', 'dt': datetime(2024, 10, 10, 8, 10)}, + 3: {'id': 3, 'session': 1, 'info': '{"defects": 1}', 'dt': datetime(2024, 10, 10, 8, 15)}} + + +@app.route('/', methods=['GET', 'POST']) +def get_all(): + if request.method == 'POST': + dto = request.get_json()['dto'] + new_id = max(events.keys()) + 1 + events[new_id] = { + 'id': new_id, + 'session': dto['session'], + 'info': dto['info'], + 'dt': datetime.now() + } + return jsonify(events[new_id]) + return jsonify(events) + + +@app.route('/', methods=['GET', 'PUT', 'DELETE']) +def get_by_id(event_id): + if event_id not in events.keys(): + return Response(status=404) + + if request.method == 'PUT': + dto = request.get_json()['dto'] + events[event_id] = { + 'session': dto['session'], + 'info': dto['info'], + 'dt': datetime.now() + } + return events[event_id] + elif request.method == 'DELETE': + events.pop(event_id) + return Response(status=200) + + return jsonify(events[event_id]) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8081) diff --git a/presnyakova_victoria_lab_3/nginx.conf b/presnyakova_victoria_lab_3/nginx.conf new file mode 100644 index 0000000..290c17b --- /dev/null +++ b/presnyakova_victoria_lab_3/nginx.conf @@ -0,0 +1,28 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 8086; + listen [::]:8086; + server_name localhost; + + location /event_service/ { + proxy_pass http://event_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 /session_service/ { + proxy_pass http://session_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/presnyakova_victoria_lab_3/readme.md b/presnyakova_victoria_lab_3/readme.md new file mode 100644 index 0000000..6c402e2 --- /dev/null +++ b/presnyakova_victoria_lab_3/readme.md @@ -0,0 +1,31 @@ +# Задание: + +- Создать 2 микросервиса, реализующих CRUD на связанных сущностях. +- Реализовать механизм синхронного обмена сообщениями между микросервисами. +- Реализовать шлюз на основе прозрачного прокси-сервера nginx. + +Вариант: Сессии и события + +## Выполнение + +Были написаны два сервиса на языке python: + +- Сервис session_service, хранящий данные о сессиях и реализующий CRUD операции с ними через HTTP запросы. +- Сервис event_service, хранящий данные о событиях и реализующий CRUD операции с ними через HTTP запросы. + +- Сервисы синхронно сообщены - сервис сессия запрашивает данные у сервиса событий для получения событий сессии. + +Для сервисов прописаны файлы Dockerfile, описывающие создание контейнеров: + +Для обоих контейнеров выбирается Python 3.9. +Оба контейнера проявляют порты, на которых работает приложение: 8081 для событий и 8082 для сессий. +В оба контейнера устанавливаются пакеты Flask и requests. +Выбирается рабочая директория /work и туда копируются файлы скриптов. +Командой запускаются сами скрипты. +Общий yaml-файл развёртки был настроен следующим образом: + +блок services, где перечислены разворачиваемые сервисы. +для каждого сервиса прописан build, где объявляется его папка и докерфайл создания и зависимости. +для сервиса nginx прописан порт для отображения вовне. + +## Видео https://drive.google.com/file/d/1my-e51bAoxUaMHKpGJmd9ZXSR5GnmORS/view?usp=sharing \ No newline at end of file diff --git a/presnyakova_victoria_lab_3/session_service/Dockerfile b/presnyakova_victoria_lab_3/session_service/Dockerfile new file mode 100644 index 0000000..ff15900 --- /dev/null +++ b/presnyakova_victoria_lab_3/session_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 + +EXPOSE 8082 + +RUN pip install Flask requests flasgger + +WORKDIR /work + +COPY session_service.py ./ + +CMD ["python", "session_service.py"] diff --git a/presnyakova_victoria_lab_3/session_service/session_service.py b/presnyakova_victoria_lab_3/session_service/session_service.py new file mode 100644 index 0000000..e11dd1b --- /dev/null +++ b/presnyakova_victoria_lab_3/session_service/session_service.py @@ -0,0 +1,62 @@ +from flask import Flask, jsonify, request, Response +from datetime import datetime +import requests + + +app = Flask(__name__) + +sessions = {0: {'id': 0, 'info': '{"distance": 1}', 'dt_start': datetime(2024, 10, 10, 8, 0), + 'dt_end': datetime(2024, 10, 11, 8, 0), 'events': [0, 1]}, + 1: {'id': 1, 'info': '{"distance": 1}', 'dt_start': datetime(2024, 10, 12, 8, 0), + 'dt_end': datetime(2024, 10, 13, 8, 0), 'events': [0, 1]}, + 2: {'id': 2, 'info': '{"distance": 1}', 'dt_start': datetime(2024, 10, 14, 8, 0), + 'dt_end': datetime(2024, 10, 15, 8, 0), 'events': [0, 1]}, + 3: {'id': 3, 'info': '{"distance": 1}', 'dt_start': datetime(2024, 10, 16, 8, 0), + 'dt_end': datetime(2024, 10, 17, 8, 0), 'events': [0, 1]}, + } + + +@app.route('/', methods=['GET', 'POST']) +def get_all(): + if request.method == 'POST': + dto = request.get_json()['dto'] + new_id = max(sessions.keys()) + 1 + sessions[new_id] = { + 'id': new_id, + 'info': dto['info'], + 'dt_start': datetime.now(), + 'dt_end': datetime.now() + datetime.timedelta(days=1) + + } + return jsonify(sessions[new_id]) + return jsonify(sessions) + + +@app.route('/', methods=['GET', 'PUT', 'DELETE']) +def get_by_id(session_id): + if session_id not in sessions.keys(): + return Response(status=404) + + if request.method == 'PUT': + dto = request.get_json()['dto'] + sessions[session_id] = { + 'info': dto['info'], + 'dt_start': datetime.now(), + 'dt_end': datetime.now() + datetime.timedelta(days=1), + } + return sessions[session_id] + elif request.method == 'DELETE': + sessions.pop(session_id) + return Response(status=200) + + session = sessions[session_id] + events = [] + for event_id in session['events']: + events.append(requests.get("http://event_service:8081/" + str(event_id)).json()) + session['events'] = events + + return jsonify(session) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', use_reloader=False, port=8082)