diff --git a/kurushina_ksenia_lab_3/README.md b/kurushina_ksenia_lab_3/README.md new file mode 100644 index 0000000..15fb9c0 --- /dev/null +++ b/kurushina_ksenia_lab_3/README.md @@ -0,0 +1,45 @@ +Лабораторная работа №3 - REST API, шлюз и синхронный обмен данными между микросервисами + +Задание + +Цель: +Изучение принципов проектирования с использованием паттерна шлюза, +организации синхронной передачи данных между микросервисами +и применения архитектурного стиля RESTful API. + + +Задачи: +Создание двух микросервисов, которые реализуют операции CRUD для связанных сущностей. +Реализация механизма синхронного обмена данными между микросервисами. +Настройка шлюза на базе Nginx в качестве прозрачного прокси-сервера. +Микросервисы: +book_service — сервис, который управляет книгами. +shelf_service — сервис, который обрабатывает данные о полках. +Связь между микросервисами: +Один документ (book) может иметь множество связанных предметов (shelf) (соотношение 1 ко многим). +Как запустить проект: +Для запуска приложения необходимо выполнить команду: + +docker-compose up +Описание работы: +Для разработки микросервисов был выбран язык программирования Python. + +Синхронный обмен данными +Сервис book_service отправляет HTTP-запросы к shelf_service +при выполнении определенных операций CRUD. Это позволяет получать актуальную информацию о книгах, +связанных с конкретными полками. + +Docker Compose +Конфигурационный файл docker-compose.yml +представляет собой многоконтейнерное приложение, которое включает в себя три сервиса: +book_service, shelf_service и nginx. Функция маршрутизации возложена на сервер Nginx, +который обрабатывает запросы и перенаправляет их на соответствующие микросервисы. + +Nginx +Конфигурационный файл Nginx определяет настройки веб-сервера и +обратного прокси, который управляет входящими запросами +и направляет их на соответствующие сервисы. + +ВИДЕО + +https://cloud.mail.ru/public/Aijk/T8myacqz5 \ No newline at end of file diff --git a/kurushina_ksenia_lab_3/book_service/Dockerfile b/kurushina_ksenia_lab_3/book_service/Dockerfile new file mode 100644 index 0000000..1804d45 --- /dev/null +++ b/kurushina_ksenia_lab_3/book_service/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.9-slim +WORKDIR /app +COPY app.py /app +RUN pip install flask requests +CMD ["python", "app.py"] diff --git a/kurushina_ksenia_lab_3/book_service/main.py b/kurushina_ksenia_lab_3/book_service/main.py new file mode 100644 index 0000000..a463152 --- /dev/null +++ b/kurushina_ksenia_lab_3/book_service/main.py @@ -0,0 +1,39 @@ +from flask import Flask, jsonify, request + +app = Flask(__name__) + +BOOKS = [] + +@app.route('/books', methods=['GET']) +def get_books(): + return jsonify(BOOKS) + +@app.route('/books/', methods=['GET']) +def get_book(id): + book = next((book for book in BOOKS if book['id'] == id), None) + if book: + return jsonify(book) + return jsonify({"message": "Book not found"}), 404 + +@app.route('/books', methods=['POST']) +def create_book(): + new_book = request.get_json() + BOOKS.append(new_book) + return jsonify(new_book), 201 + +@app.route('/books/', methods=['PUT']) +def update_book(id): + book = next((book for book in BOOKS if book['id'] == id), None) + if book: + book.update(request.get_json()) + return jsonify(book) + return jsonify({"message": "Book not found"}), 404 + +@app.route('/books/', methods=['DELETE']) +def delete_book(id): + global BOOKS + BOOKS = [book for book in BOOKS if book['id'] != id] + return '', 204 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/kurushina_ksenia_lab_3/docker-compose.yml b/kurushina_ksenia_lab_3/docker-compose.yml new file mode 100644 index 0000000..fbbe719 --- /dev/null +++ b/kurushina_ksenia_lab_3/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.8' + +services: + book_service: + build: + context: . + dockerfile: book_service/Dockerfile + ports: + - "5000:5000" + + shelf_service: + build: + context: . + dockerfile: shelf_service/Dockerfile + ports: + - "5001:5001" + + nginx: + build: + context: . + dockerfile: nginx/Dockerfile + ports: + - "80:80" diff --git a/kurushina_ksenia_lab_3/img.png b/kurushina_ksenia_lab_3/img.png new file mode 100644 index 0000000..33b1944 Binary files /dev/null and b/kurushina_ksenia_lab_3/img.png differ diff --git a/kurushina_ksenia_lab_3/img_1.png b/kurushina_ksenia_lab_3/img_1.png new file mode 100644 index 0000000..2f5f290 Binary files /dev/null and b/kurushina_ksenia_lab_3/img_1.png differ diff --git a/kurushina_ksenia_lab_3/nginx/Dockerfile b/kurushina_ksenia_lab_3/nginx/Dockerfile new file mode 100644 index 0000000..9e620af --- /dev/null +++ b/kurushina_ksenia_lab_3/nginx/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:alpine + +COPY nginx.conf /etc/nginx/nginx.conf diff --git a/kurushina_ksenia_lab_3/nginx/nginx.conf b/kurushina_ksenia_lab_3/nginx/nginx.conf new file mode 100644 index 0000000..538e0c5 --- /dev/null +++ b/kurushina_ksenia_lab_3/nginx/nginx.conf @@ -0,0 +1,21 @@ +server { + listen 80; + + location /books { + proxy_pass http://book_service:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + location /shelves { + proxy_pass http://shelf_service:5001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/kurushina_ksenia_lab_3/shelf_service/Dockerfile b/kurushina_ksenia_lab_3/shelf_service/Dockerfile new file mode 100644 index 0000000..1804d45 --- /dev/null +++ b/kurushina_ksenia_lab_3/shelf_service/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.9-slim +WORKDIR /app +COPY app.py /app +RUN pip install flask requests +CMD ["python", "app.py"] diff --git a/kurushina_ksenia_lab_3/shelf_service/main.py b/kurushina_ksenia_lab_3/shelf_service/main.py new file mode 100644 index 0000000..b47130b --- /dev/null +++ b/kurushina_ksenia_lab_3/shelf_service/main.py @@ -0,0 +1,43 @@ +from flask import Flask, jsonify, request +import requests + +app = Flask(__name__) + +SHELVES = [] + +@app.route('/shelves', methods=['GET']) +def get_shelves(): + book_service_url = "http://book_service:5000/books" + response = requests.get(book_service_url) + books = response.json() + + shelves = {} + for book in books: + if book["shelf"] not in shelves: + shelves[book["shelf"]] = [] + shelves[book["shelf"]].append(book) + + return jsonify(shelves) + +@app.route('/shelves', methods=['POST']) +def create_shelf(): + new_shelf = request.get_json() + SHELVES.append(new_shelf) + return jsonify(new_shelf), 201 + +@app.route('/shelves/', methods=['PUT']) +def update_shelf(name): + shelf = next((shelf for shelf in SHELVES if shelf['name'] == name), None) + if shelf: + shelf.update(request.get_json()) + return jsonify(shelf) + return jsonify({"message": "Shelf not found"}), 404 + +@app.route('/shelves/', methods=['DELETE']) +def delete_shelf(name): + global SHELVES + SHELVES = [shelf for shelf in SHELVES if shelf['name'] != name] + return '', 204 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5001)