2023-11-26 01:40:12 +04:00
|
|
|
|
# Лабораторная работа 3. Вариант 5.
|
|
|
|
|
|
|
|
|
|
### Как запустить
|
|
|
|
|
В директории с файлом `docker-compose.yaml` выполнить команду:
|
|
|
|
|
```
|
|
|
|
|
docker-compose up -d
|
|
|
|
|
```
|
|
|
|
|
Это запустит `docker-compose`, который создаст контейнер и развернет в нем 3 контейнера.
|
|
|
|
|
|
|
|
|
|
### Файловая иерархия
|
2023-11-21 23:45:46 +04:00
|
|
|
|
```
|
|
|
|
|
basharin_sevastyan_lab_3/
|
|
|
|
|
|-- user_service/
|
|
|
|
|
| |-- Dockerfile
|
|
|
|
|
| |-- requirements.txt
|
|
|
|
|
| |-- user_service.py
|
|
|
|
|
|-- order_service/
|
|
|
|
|
| |-- Dockerfile
|
|
|
|
|
| |-- requirements.txt
|
|
|
|
|
| |-- order_service.py
|
|
|
|
|
|-- nginx/
|
|
|
|
|
| |-- Dockerfile
|
|
|
|
|
| |-- nginx.conf
|
|
|
|
|
|-- docker-compose.yml
|
|
|
|
|
```
|
|
|
|
|
|
2023-11-26 01:40:12 +04:00
|
|
|
|
### Описание работы
|
|
|
|
|
#### Описание предметной области
|
|
|
|
|
Объекты микросервисов буду связаны следующим образом:
|
|
|
|
|
```
|
|
|
|
|
user (single) <- order (many)
|
|
|
|
|
```
|
|
|
|
|
#### Синхронный обмен сообщениями
|
|
|
|
|
`order_service` будет отправлять http-запрос на `user_service` при определенных crud операциях. Например, при создании
|
|
|
|
|
экземпляра `order`, будет отправлен запрос на добавление `order` к определенному `user`:
|
|
|
|
|
```python
|
|
|
|
|
# CREATE
|
|
|
|
|
@app.route('/add_order/<int:user_id>_<string:product>', methods=['POST'])
|
|
|
|
|
def create_order(user_id, product):
|
|
|
|
|
order = {'id': len(orders) + 1,
|
|
|
|
|
'user_id': user_id,
|
|
|
|
|
'product': product,
|
|
|
|
|
'action': 'create'}
|
|
|
|
|
orders.append(order)
|
|
|
|
|
# Отправка сообщения о создании заказа
|
|
|
|
|
requests.post("http://user-service:5001/event", json=order)
|
|
|
|
|
|
|
|
|
|
return jsonify(order)
|
|
|
|
|
```
|
|
|
|
|
В `user_service` этот запрос обрабатывается следующим образом:
|
|
|
|
|
```python
|
|
|
|
|
@app.route('/event', methods=['POST'])
|
|
|
|
|
def event():
|
|
|
|
|
print('получено сообщение')
|
|
|
|
|
data = request.get_json()
|
|
|
|
|
print(data)
|
|
|
|
|
user_id = data.get('user_id')
|
|
|
|
|
|
|
|
|
|
if data['action'] == 'create':
|
|
|
|
|
# Создание заказа у пользователя
|
|
|
|
|
user = next((user for user in users if user['id'] == user_id), None)
|
|
|
|
|
if user:
|
|
|
|
|
order_id = len(user.get('orders', [])) + 1
|
|
|
|
|
order = {'id': order_id, 'product': data['product']}
|
|
|
|
|
user.setdefault('orders', []).append(order)
|
|
|
|
|
print(f"Order created for user {user_id}: {order}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"User not found for order creation: {user_id}")
|
|
|
|
|
|
|
|
|
|
elif data['action'] == 'update':
|
|
|
|
|
# Обновление заказа у пользователя
|
|
|
|
|
user = next((user for user in users if user['id'] == user_id), None)
|
|
|
|
|
if user:
|
|
|
|
|
order_id = data.get('id')
|
|
|
|
|
order = next((order for order in user['orders'] if order['id'] == order_id), None)
|
|
|
|
|
if order:
|
|
|
|
|
order['product'] = data['product']
|
|
|
|
|
print(f"Order updated for user {user_id}: {order}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Order not found for update: {order_id}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"User not found for order update: {user_id}")
|
|
|
|
|
|
|
|
|
|
elif data['action'] == 'delete':
|
|
|
|
|
# Удаление заказа у пользователя
|
|
|
|
|
user = next((user for user in users if user['id'] == user_id), None)
|
|
|
|
|
if user:
|
|
|
|
|
order_id = user.get('id')
|
|
|
|
|
user['orders'] = [order for order in user.get('orders', []) if order['id'] != order_id]
|
|
|
|
|
print(f"Order deleted for user {user_id}: {order_id}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"User not found for order deletion: {user_id}")
|
|
|
|
|
return jsonify({'result': True})
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Описание docker-compose
|
2023-11-21 23:45:46 +04:00
|
|
|
|
```yaml
|
2023-11-26 01:40:12 +04:00
|
|
|
|
version: '3.8'
|
2023-11-21 23:45:46 +04:00
|
|
|
|
|
|
|
|
|
services:
|
|
|
|
|
user-service:
|
|
|
|
|
build:
|
|
|
|
|
context: ./user_service
|
|
|
|
|
ports:
|
|
|
|
|
- "5001:5001"
|
2023-11-26 01:40:12 +04:00
|
|
|
|
networks:
|
|
|
|
|
- my_network
|
|
|
|
|
restart: always
|
2023-11-21 23:45:46 +04:00
|
|
|
|
|
|
|
|
|
order-service:
|
|
|
|
|
build:
|
|
|
|
|
context: ./order_service
|
|
|
|
|
ports:
|
|
|
|
|
- "5002:5002"
|
2023-11-26 01:40:12 +04:00
|
|
|
|
networks:
|
|
|
|
|
- my_network
|
|
|
|
|
restart: always
|
2023-11-21 23:45:46 +04:00
|
|
|
|
|
|
|
|
|
nginx:
|
2023-11-26 01:40:12 +04:00
|
|
|
|
image: nginx:latest
|
2023-11-21 23:45:46 +04:00
|
|
|
|
ports:
|
|
|
|
|
- "80:80"
|
|
|
|
|
depends_on:
|
|
|
|
|
- user-service
|
|
|
|
|
- order-service
|
2023-11-26 01:40:12 +04:00
|
|
|
|
networks:
|
|
|
|
|
- my_network
|
|
|
|
|
volumes:
|
|
|
|
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
|
|
|
|
restart: always
|
|
|
|
|
|
|
|
|
|
networks:
|
|
|
|
|
my_network:
|
|
|
|
|
driver: bridge
|
2023-11-21 23:45:46 +04:00
|
|
|
|
```
|
|
|
|
|
|
2023-11-26 01:40:12 +04:00
|
|
|
|
### Dockerfile микросервисов
|
2023-11-21 23:45:46 +04:00
|
|
|
|
```dockerfile
|
|
|
|
|
# user_service/Dockerfile
|
|
|
|
|
FROM python:3.11
|
|
|
|
|
WORKDIR /app
|
|
|
|
|
COPY requirements.txt .
|
|
|
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
2023-11-26 01:40:12 +04:00
|
|
|
|
COPY . /app
|
|
|
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:5001", "user_service:app"]
|
2023-11-21 23:45:46 +04:00
|
|
|
|
```
|
|
|
|
|
```dockerfile
|
2023-11-26 01:40:12 +04:00
|
|
|
|
# order_service/Dockerfile
|
2023-11-21 23:45:46 +04:00
|
|
|
|
FROM python:3.11
|
|
|
|
|
WORKDIR /app
|
|
|
|
|
COPY requirements.txt .
|
|
|
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
2023-11-26 01:40:12 +04:00
|
|
|
|
COPY . /app
|
|
|
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:5002", "order_service:app"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Dockerfile nginx
|
|
|
|
|
```dockerfile
|
|
|
|
|
# nginx/Dockerfile
|
|
|
|
|
FROM nginx
|
|
|
|
|
COPY nginx.conf /etc/nginx/nginx.conf
|
|
|
|
|
EXPOSE 80
|
|
|
|
|
CMD ["nginx", "-g", "daemon off;"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Видео
|
|
|
|
|
https://youtu.be/3-iF9xBHvCU
|