antonov_dmitry_lab3_ready
This commit is contained in:
parent
b166d347a9
commit
fe7928f10c
@ -1,67 +1,54 @@
|
|||||||
# Лабораторная работа №3 - Знакомство с docker и docker-compose
|
# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами
|
||||||
|
|
||||||
Разверните 3 сервиса на выбор в контейнерах docker с помощью docker-compose.
|
Изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API.
|
||||||
Требования и docker-compose:
|
|
||||||
|
|
||||||
Несколько контейнеров.
|
Создать два микросервиса.
|
||||||
Хотя бы один volume.
|
|
||||||
Хотя бы один порт, проброшенный на хост.
|
|
||||||
При этом разворачивание системы должно пройти до конца. Например, должен быть создан
|
|
||||||
администратор и система должна корректно функционировать. Это необходимо будет предоставить
|
|
||||||
в отчёте, поэтому не забывайте делать скриншоты.
|
|
||||||
|
|
||||||
# Выбранные сервисы
|
Каждый сервис реализует CRUD-операции: список записей, подробности конкретной записи, создание, удаление и изменение записи.
|
||||||
|
В качестве хранилища данных может выступать оперативная память приложения или база данных.
|
||||||
|
Сущности необходимо подобрать по следующим критериям:
|
||||||
|
|
||||||
* mediawiki - движок вики
|
Они должны быть связаны с предполагаемой темой диплома.
|
||||||
* drupal - популярная система управления контентом
|
Они должны быть связаны как "1-ко-многим".
|
||||||
* wordpress - популярная система управления контентом.
|
|
||||||
|
# Задачи
|
||||||
|
|
||||||
|
* Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
|
||||||
|
* Реализовать механизм синхронного обмена сообщениями между микросервисами.
|
||||||
|
* Реализовать шлюз на основе прозрачного прокси-сервера nginx.
|
||||||
|
|
||||||
# Запуск
|
# Запуск
|
||||||
|
|
||||||
Командой в консоли проекта "docker-compose up -d"
|
Командой в консоли проекта "docker-compose up -d"
|
||||||
|
|
||||||
# Описание работы:
|
# Описание работы:
|
||||||
Развернули три сервиса плюс базу данных к ним.
|
Развернули два приложения
|
||||||
Подробное описание для docker-compose дано в комментариях.
|
|
||||||
|
|
||||||
1. mediawiki:
|
1. Сервис с врачами:
|
||||||
- доступ на http://localhost:8080/
|
- доступ на http://localhost:5000/
|
||||||
|
|
||||||
2. drupal:
|
2. Сервис с пациентами:
|
||||||
- доступ на http://localhost:8081/
|
- доступ на http://localhost:5001/
|
||||||
|
|
||||||
3. wordpress:
|
Сервисы связываются друг с другом через ссылку и библиотеку requests
|
||||||
- доступ на http://localhost:8082/
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<div>Старт сервисов</div>
|
<div>Старт сервисов</div>
|
||||||
<img src="screens/img.png" width="650" title="Старт сервисов">
|
<img src="screens/img1.png" width="650" title="Сервисы">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div>Сервисы</div>
|
<div>Сервис врачей</div>
|
||||||
<img src="screens/img_1.png" width="650" title="Сервисы">
|
<img src="screens/img2.png" width="650" title="Сервис врачей">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div>Images</div>
|
<div>Сервис пациентов</div>
|
||||||
<img src="screens/img_2.png" width="650" title="Сервисы">
|
<img src="screens/img3.png" width="650" title="Сервис пациентов">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div>Volumes</div>
|
<div>Связь сервисов через библиотеку requests</div>
|
||||||
<img src="screens/img_3.png" width="650" title="Сервисы">
|
<img src="screens/img4.png" width="650" title="Связь сервисов">
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<div>Сервис 1</div>
|
|
||||||
<img src="screens/img_4.png" width="650" title="Сервис 1">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<div>Сервис 2</div>
|
|
||||||
<img src="screens/img_5.png" width="650" title="Сервис 2">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<div>Сервис 3</div>
|
|
||||||
<img src="screens/img_6.png" width="650" title="Сервис 3">
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Ссылка на видео
|
# Ссылка на видео
|
||||||
https://disk.yandex.ru/i/nG5KrHy_DsQxuw
|
https://disk.yandex.ru/i/3o4aLuqp1EpbJg
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ services:
|
|||||||
nginx:
|
nginx:
|
||||||
image: nginx
|
image: nginx
|
||||||
ports:
|
ports:
|
||||||
- "8085:8085"
|
- "80:80"
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx.conf:/etc/nginx/conf.d/nginx.conf
|
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
depends_on:
|
depends_on:
|
||||||
- service_a
|
- service_a
|
||||||
- service_b
|
- service_b
|
@ -1,13 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 8085;
|
|
||||||
listen [::]:8085;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
location /service_a/ {
|
|
||||||
proxy_pass http://127.0.0.1:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /service_b/ {
|
|
||||||
proxy_pass http://127.0.0.1:5001;
|
|
||||||
}
|
|
||||||
}
|
|
17
antonov_dmitry_lab_3/nginx/nginx.conf
Normal file
17
antonov_dmitry_lab_3/nginx/nginx.conf
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location /app1/ {
|
||||||
|
proxy_pass http://localhost:5000/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /app2/ {
|
||||||
|
proxy_pass http://localhost:5001/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
}
|
BIN
antonov_dmitry_lab_3/screens/img1.png
Normal file
BIN
antonov_dmitry_lab_3/screens/img1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
antonov_dmitry_lab_3/screens/img2.png
Normal file
BIN
antonov_dmitry_lab_3/screens/img2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
BIN
antonov_dmitry_lab_3/screens/img3.png
Normal file
BIN
antonov_dmitry_lab_3/screens/img3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
BIN
antonov_dmitry_lab_3/screens/img4.png
Normal file
BIN
antonov_dmitry_lab_3/screens/img4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
@ -1,42 +1,98 @@
|
|||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
|
import requests
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# "customers"
|
# набор данных докторов с их пациентами
|
||||||
customers_data = []
|
doctors_data = [
|
||||||
|
{
|
||||||
|
'id': 1,
|
||||||
|
'name': 'Doctor A',
|
||||||
|
'email': 'doctor.a@example.com',
|
||||||
|
'patients': [
|
||||||
|
{'id': 1, 'name': 'Patient A1', 'email': 'patient.a1@example.com'},
|
||||||
|
{'id': 2, 'name': 'Patient A2', 'email': 'patient.a2@example.com'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 2,
|
||||||
|
'name': 'Doctor B',
|
||||||
|
'email': 'doctor.b@example.com',
|
||||||
|
'patients': [
|
||||||
|
{'id': 3, 'name': 'Patient B1', 'email': 'patient.b1@example.com'},
|
||||||
|
{'id': 4, 'name': 'Patient B2', 'email': 'patient.b2@example.com'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 3,
|
||||||
|
'name': 'Doctor C',
|
||||||
|
'email': 'doctor.c@example.com',
|
||||||
|
'patients': [
|
||||||
|
{'id': 5, 'name': 'Patient C1', 'email': 'patient.c1@example.com'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# URL для сервиса пациентов
|
||||||
|
patients_service_url = "http://localhost/app2/patients"
|
||||||
|
|
||||||
@app.route('/service_a/', methods=['GET'])
|
@app.route('/', methods=['GET'])
|
||||||
def get_index():
|
def get_index():
|
||||||
return "Hello from service_a"
|
return "это первый сервис"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/service_a/customers', methods=['GET'])
|
@app.route('/doctors', methods=['GET'])
|
||||||
def get_customers():
|
def get_doctors():
|
||||||
return jsonify(customers_data)
|
return jsonify(doctors_data)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/service_a/customers', methods=['POST'])
|
@app.route('/doctors', methods=['POST'])
|
||||||
def create_customer():
|
def create_doctor():
|
||||||
new_customer = request.json
|
new_doctor = request.json
|
||||||
customers_data.append(new_customer)
|
# уникальный id для нового доктора
|
||||||
return jsonify(new_customer), 201
|
new_doctor['id'] = len(doctors_data) + 1
|
||||||
|
new_doctor['patients'] = []
|
||||||
|
doctors_data.append(new_doctor)
|
||||||
|
return jsonify(new_doctor), 201
|
||||||
|
|
||||||
|
|
||||||
@app.route('/service_a/customers/<int:id>', methods=['PUT'])
|
@app.route('/doctors/<int:id>', methods=['PUT'])
|
||||||
def update_customer(id):
|
def update_doctor(id):
|
||||||
for customer in customers_data:
|
for doctor in doctors_data:
|
||||||
if customer['id'] == id:
|
if doctor['id'] == id:
|
||||||
customer.update(request.json)
|
doctor.update(request.json)
|
||||||
return jsonify(customer), 200
|
return jsonify(doctor), 200
|
||||||
return jsonify({'error': 'Customer not found'}), 404
|
return jsonify({'error': 'Доктор не найден'}), 404
|
||||||
|
|
||||||
|
|
||||||
@app.route('/service_a/customers/<int:id>', methods=['DELETE'])
|
@app.route('/doctors/<int:id>', methods=['DELETE'])
|
||||||
def delete_customer(id):
|
def delete_doctor(id):
|
||||||
global customers_data
|
global doctors_data
|
||||||
customers_data = [customer for customer in customers_data if customer['id'] != id]
|
doctors_data = [doctor for doctor in doctors_data if doctor['id'] != id]
|
||||||
return jsonify({'message': 'Customer deleted'}), 200
|
return jsonify({'message': 'Доктор удален'}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/doctors/<int:id>/patients', methods=['GET'])
|
||||||
|
def get_doctor_patients(id):
|
||||||
|
for doctor in doctors_data:
|
||||||
|
if doctor['id'] == id:
|
||||||
|
return jsonify(doctor['patients'])
|
||||||
|
return jsonify({'error': 'Доктор не найден'}), 404
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/doctors/<int:id>/patients', methods=['POST'])
|
||||||
|
def create_doctor_patient(id):
|
||||||
|
for doctor in doctors_data:
|
||||||
|
if doctor['id'] == id:
|
||||||
|
new_patient = request.json
|
||||||
|
# назначить уникальный id новому пациенту
|
||||||
|
new_patient['id'] = len(doctor['patients']) + 1
|
||||||
|
doctor['patients'].append(new_patient)
|
||||||
|
|
||||||
|
requests.post(patients_service_url, json=new_patient)
|
||||||
|
|
||||||
|
return jsonify(new_patient), 201
|
||||||
|
return jsonify({'error': 'Доктор не найден'}), 404
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,42 +1,69 @@
|
|||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
|
import requests
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# "clients"
|
# набор данных пациентов и их врачей
|
||||||
clients_data = []
|
patients_data = [
|
||||||
|
{'id': 1, 'name': 'Patient A', 'email': 'patient.a@example.com', 'doctor_id': 1},
|
||||||
|
{'id': 2, 'name': 'Patient B', 'email': 'patient.b@example.com', 'doctor_id': 2},
|
||||||
|
{'id': 3, 'name': 'Patient C', 'email': 'patient.c@example.com', 'doctor_id': 1},
|
||||||
|
]
|
||||||
|
|
||||||
|
# URL сервиса докторов
|
||||||
|
doctor_service_url = "http://localhost:5000"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', methods=['GET'])
|
@app.route('/', methods=['GET'])
|
||||||
def get_index():
|
def get_index():
|
||||||
return "Hello from service_b"
|
return "это второй сервис"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/clients', methods=['GET'])
|
@app.route('/patients', methods=['GET'])
|
||||||
def get_clients():
|
def get_patients():
|
||||||
return jsonify(clients_data)
|
return jsonify(patients_data)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/clients', methods=['POST'])
|
@app.route('/patients/<int:id>', methods=['GET'])
|
||||||
def create_client():
|
def get_patient(id):
|
||||||
new_client = request.json
|
for patient in patients_data:
|
||||||
clients_data.append(new_client)
|
if patient['id'] == id:
|
||||||
return jsonify(new_client), 201
|
return jsonify(patient)
|
||||||
|
return jsonify({'error': 'Пациент не найден'}), 404
|
||||||
|
|
||||||
|
|
||||||
@app.route('/clients/<int:id>', methods=['PUT'])
|
@app.route('/patients', methods=['POST'])
|
||||||
def update_client(id):
|
def create_patient():
|
||||||
for client in clients_data:
|
new_patient = request.json
|
||||||
if client['id'] == id:
|
# назначить уникальный id новому пациенту
|
||||||
client.update(request.json)
|
new_patient['id'] = len(patients_data) + 1
|
||||||
return jsonify(client), 200
|
patients_data.append(new_patient)
|
||||||
return jsonify({'error': 'Client not found'}), 404
|
|
||||||
|
# отправляем запрос другому сервису
|
||||||
|
requests.post(f"{doctor_service_url}/doctors/1/patients", json=new_patient)
|
||||||
|
|
||||||
|
return jsonify(new_patient), 201
|
||||||
|
|
||||||
|
|
||||||
@app.route('/clients/<int:id>', methods=['DELETE'])
|
@app.route('/patients/<int:id>', methods=['PUT'])
|
||||||
def delete_client(id):
|
def update_patient(id):
|
||||||
global clients_data
|
for patient in patients_data:
|
||||||
clients_data = [client for client in clients_data if client['id'] != id]
|
if patient['id'] == id:
|
||||||
return jsonify({'message': 'Client deleted'}), 200
|
patient.update(request.json)
|
||||||
|
# отправляем запрос другому сервису
|
||||||
|
response = requests.put(f"{doctor_service_url}/doctors/1/patients/{id}", json=request.json)
|
||||||
|
return jsonify(patient), 200
|
||||||
|
return jsonify({'error': 'Пациент не найден'}), 404
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/patients/<int:id>', methods=['DELETE'])
|
||||||
|
def delete_patient(id):
|
||||||
|
# отправляем запрос другому сервису
|
||||||
|
response = requests.delete(f"{doctor_service_url}/doctors/1/patients/{id}")
|
||||||
|
|
||||||
|
global patients_data
|
||||||
|
patients_data = [patient for patient in patients_data if patient['id'] != id]
|
||||||
|
return jsonify({'message': 'Пациент удален'}), 200
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user