morozov_vladimir_lab_4 is ready #174
0
morozov_vladimir_lab_3/.gitignore
vendored
Normal file
18
morozov_vladimir_lab_3/docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: '3'
|
||||||
|
# Объявляем сервисы
|
||||||
|
services:
|
||||||
|
artists_srv: # сервис приложения артистов
|
||||||
|
build: ./service_artists/
|
||||||
|
|
||||||
|
paints_srv: # сервис приложения картин
|
||||||
|
build: ./service_paints/
|
||||||
|
|
||||||
|
gateway: # сервис nginx
|
||||||
|
image: nginx:latest # назначаем его образ
|
||||||
|
ports: # пробрасываем порта
|
||||||
|
- 8080:8080
|
||||||
|
volumes: # перекидываем конфигурационный файл
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
depends_on: # ожидаем запуска предыдущих сервисов
|
||||||
|
- artists_srv
|
||||||
|
- paints_srv
|
39
morozov_vladimir_lab_3/nginx.conf
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
http
|
||||||
|
{
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
listen [::]:8080;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location /artists/ {
|
||||||
|
proxy_pass http://artists_srv:8001/artists/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /artists/docs {
|
||||||
|
proxy_pass http://artists_srv:8001/docs;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /paints/docs {
|
||||||
|
proxy_pass http://paints_srv:8002/docs;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /paints/ {
|
||||||
|
proxy_pass http://paints_srv:8002/paints/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
26
morozov_vladimir_lab_3/readme.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами
|
||||||
|
|
||||||
|
## Разработанные приложения
|
||||||
|
В рамках л/р были разработаны 2 приложения:
|
||||||
|
1) Сервис для работы с сущностью художник(artist). Сущность имеет следующие поля:
|
||||||
|
1) uid (номер)
|
||||||
|
2) name (ФИО)
|
||||||
|
3) year (год рождения)
|
||||||
|
2) Сервис для работы с сущностью картина(paint). Сущность имеет следующие поля:
|
||||||
|
1) uid (номер)
|
||||||
|
2) title (название)
|
||||||
|
3) year (год создания)
|
||||||
|
4) author (номер художника)
|
||||||
|
Один художник(один) может создать несколько картин(многие)
|
||||||
|
## Приготовления
|
||||||
|
Для обеспечения нужной работоспособности нашего приложения был использован веб-сервер Nginx, который можем использовать в роли прокси сервера.
|
||||||
|
Для этого нужно было развернуть его в отдельном контейнере и настроить его конфигурационный файл, в которым мы описывали прослушиваемые адреса и куда нужно перенаправлять.
|
||||||
|
Сервисы развернули в обычном порядке: написали код приложения, создали докер-файл, записали в докер-композе.
|
||||||
|
## Запуск
|
||||||
|
Для запуска приложения используем команду:
|
||||||
|
```
|
||||||
|
docker-compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запись тестирования
|
||||||
|
Работа приложения представлена в [видео](https://disk.yandex.ru/i/8yuoSm0QSR9wGw)
|
77
morozov_vladimir_lab_3/service_artists/app.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from fastapi import FastAPI, Body
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
|
||||||
|
app = FastAPI(title="Artists service")
|
||||||
|
# Сервис для работы с художниками
|
||||||
|
# класс сущности художник
|
||||||
|
class artist:
|
||||||
|
def __init__(self, name, year, uid=""):
|
||||||
|
if len(uid) == 0:
|
||||||
|
self.uid = str(uuid.uuid4())
|
||||||
|
else:
|
||||||
|
self.uid = uid
|
||||||
|
self.name = name
|
||||||
|
self.year = year
|
||||||
|
|
||||||
|
# Первоначальные данные
|
||||||
|
artists = [
|
||||||
|
artist("Vincent van Gogh","1853","d1c02854-76d8-4a35-be5c-076f091a67c0"),
|
||||||
|
artist("Claude Monet","1840","41e2dadc-1aa8-4f14-b1e8-7fc5664d1cdf"),
|
||||||
|
artist("Ilya Repin","1844", "591f8c2f-1937-44a1-b1f8-ff1f8b52cece")]
|
||||||
|
# Получение всех художников
|
||||||
|
@app.get("/artists/")
|
||||||
|
async def get_all():
|
||||||
|
json_data = jsonable_encoder(artists)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
# Получение конкретного художника
|
||||||
|
@app.get("/artists/{uid}")
|
||||||
|
def get_uid(uid):
|
||||||
|
for art in artists:
|
||||||
|
if art.uid == uid:
|
||||||
|
json_data = jsonable_encoder(art)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
# Создание нового художника
|
||||||
|
@app.post("/artists/")
|
||||||
|
def create(name = Body(embed=True), year = Body(embed=True)):
|
||||||
|
for art in artists:
|
||||||
|
if art.name.lower() == name.lower():
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
new_artist = artist(name,year)
|
||||||
|
artists.append(new_artist)
|
||||||
|
json_data = jsonable_encoder(new_artist)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
# Изменение данных о художники
|
||||||
|
@app.put("/artists/{uid}")
|
||||||
|
def update(uid, name = Body(embed=True), year = Body(embed=True)):
|
||||||
|
for art in artists:
|
||||||
|
if uid == art.uid:
|
||||||
|
art.name = name
|
||||||
|
art.year = year
|
||||||
|
json_data = jsonable_encoder(art)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
# Удаление художника
|
||||||
|
@app.delete("/artists/{uid}")
|
||||||
|
def delete(uid):
|
||||||
|
ind = 0
|
||||||
|
find = False
|
||||||
|
for art in artists:
|
||||||
|
if art.uid == uid:
|
||||||
|
find = True
|
||||||
|
break
|
||||||
|
ind += 1
|
||||||
|
|
||||||
|
if find:
|
||||||
|
artists.pop(ind)
|
||||||
|
return JSONResponse(content={"message": "Resource Deleted"}, status_code=200)
|
||||||
|
else:
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
|
||||||
|
if __name__ == '__main__' :
|
||||||
|
uvicorn.run("app:app",host="0.0.0.0", port=8001,)
|
10
morozov_vladimir_lab_3/service_artists/dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# объявляем базовый образ, на основе которого будет все построено
|
||||||
|
FROM "python:3.9-slim"
|
||||||
|
# назначаем основную рабочую директорию
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
# копируем содержимое текущей папке (скрипт питона) в контейнер, в основную рабочую папку
|
||||||
|
COPY . .
|
||||||
|
# установка req
|
||||||
|
RUN pip install -r req.txt
|
||||||
|
# при запуске образа выполняем команду запуска приложения
|
||||||
|
CMD [ "python", "app.py"]
|
4
morozov_vladimir_lab_3/service_artists/req.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fastapi[all]
|
||||||
|
uuid
|
||||||
|
uvicorn
|
||||||
|
requests
|
95
morozov_vladimir_lab_3/service_paints/app.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
import requests
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from fastapi import FastAPI, Body
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
|
||||||
|
app = FastAPI(title="Paints service")
|
||||||
|
# Сервис для работы с картинами
|
||||||
|
# Класс картины
|
||||||
|
class paint:
|
||||||
|
def __init__(self, title,year,author):
|
||||||
|
self.uid = str(uuid.uuid4())
|
||||||
|
self.title = title
|
||||||
|
self.year = year
|
||||||
|
self.author = author
|
||||||
|
|
||||||
|
# Первоначальные данные
|
||||||
|
paints = [
|
||||||
|
paint("Sunflowers","1887", "d1c02854-76d8-4a35-be5c-076f091a67c0"),
|
||||||
|
paint("Self-portrait with a severed ear and a tube","1889", "d1c02854-76d8-4a35-be5c-076f091a67c0"),
|
||||||
|
paint("Boatmen on the Volga","1873", "591f8c2f-1937-44a1-b1f8-ff1f8b52cece")]
|
||||||
|
|
||||||
|
# Получение всех картин
|
||||||
|
@app.get("/paints/")
|
||||||
|
async def get_all():
|
||||||
|
json_data = jsonable_encoder(paints)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
# Получение конкретной картины
|
||||||
|
@app.get("/paints/{uid}")
|
||||||
|
def get_uid(uid):
|
||||||
|
for art in paints:
|
||||||
|
if art.uid == uid:
|
||||||
|
response = requests.get(f"http://artists_srv:8001/artists/{art.author}")
|
||||||
|
author = response.json()
|
||||||
|
result = {
|
||||||
|
"uid":art.uid,
|
||||||
|
"title":art.title,
|
||||||
|
"year":art.year,
|
||||||
|
"authorUid":art.author,
|
||||||
|
"author":author
|
||||||
|
}
|
||||||
|
json_data = jsonable_encoder(result)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
# Создание новой картины
|
||||||
|
@app.post("/paints/")
|
||||||
|
def create(title = Body(embed=True), year = Body(embed=True), author = Body(embed=True)):
|
||||||
|
for art in paints:
|
||||||
|
if art.title.lower() == title.lower():
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
response = requests.get(f"http://artists_srv:8001/artists/{author}")
|
||||||
|
if response.status_code == 404:
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
new_paint = paint(title,year, author)
|
||||||
|
paints.append(new_paint)
|
||||||
|
json_data = jsonable_encoder(new_paint)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
# Обновление данных о картине
|
||||||
|
@app.put("/paints/{uid}")
|
||||||
|
def update(uid, title = Body(embed=True), year = Body(embed=True), author = Body(embed=True)):
|
||||||
|
response = requests.get(f"http://artists_srv:8001/artists/{author}")
|
||||||
|
print(author)
|
||||||
|
print(response.status_code)
|
||||||
|
if response.status_code == 404:
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
for art in paints:
|
||||||
|
if uid == art.uid:
|
||||||
|
art.title = title
|
||||||
|
art.year = year
|
||||||
|
art.author = author
|
||||||
|
json_data = jsonable_encoder(art)
|
||||||
|
return JSONResponse(json_data)
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
# Удаление картины
|
||||||
|
@app.delete("/paints/{uid}")
|
||||||
|
def delete(uid):
|
||||||
|
ind = 0
|
||||||
|
find = False
|
||||||
|
for art in paints:
|
||||||
|
if art.uid == uid:
|
||||||
|
find = True
|
||||||
|
break
|
||||||
|
ind += 1
|
||||||
|
|
||||||
|
if find:
|
||||||
|
paints.pop(ind)
|
||||||
|
return JSONResponse(content={"message": "Resource Deleted"}, status_code=200)
|
||||||
|
else:
|
||||||
|
return JSONResponse(content={"message": "Resource Not Found"}, status_code=404)
|
||||||
|
|
||||||
|
if __name__ == '__main__' :
|
||||||
|
uvicorn.run("app:app", host="0.0.0.0", port=8002,)
|
10
morozov_vladimir_lab_3/service_paints/dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# объявляем базовый образ, на основе которого будет все построено
|
||||||
|
FROM "python:3.9-slim"
|
||||||
|
# назначаем основную рабочую директорию
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
# копируем содержимое текущей папке (скрипт питона) в контейнер, в основную рабочую папку
|
||||||
|
COPY . .
|
||||||
|
# установка зависимостей
|
||||||
|
RUN pip install -r req.txt
|
||||||
|
# при запуске образа выполняем команду запуска приложения
|
||||||
|
CMD [ "python", "app.py"]
|
4
morozov_vladimir_lab_3/service_paints/req.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fastapi[all]
|
||||||
|
uuid
|
||||||
|
uvicorn
|
||||||
|
requests
|
BIN
morozov_vladimir_lab_4/Teacher_student_message/FirstTest.png
Normal file
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 57 KiB |
BIN
morozov_vladimir_lab_4/Teacher_student_message/SecondTest.png
Normal file
After Width: | Height: | Size: 374 KiB |
After Width: | Height: | Size: 62 KiB |
@ -0,0 +1,24 @@
|
|||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
channel.basic_qos(prefetch_count=1)
|
||||||
|
channel.exchange_declare(exchange='grade_book', exchange_type='fanout')
|
||||||
|
|
||||||
|
result = channel.queue_declare(queue='cool_student', exclusive=True)
|
||||||
|
queue_name = result.method.queue
|
||||||
|
|
||||||
|
channel.queue_bind(exchange='grade_book', queue=queue_name)
|
||||||
|
|
||||||
|
print(' [*] Waiting for logs. To exit press CTRL+C')
|
||||||
|
|
||||||
|
def callback(ch, method, properties, body):
|
||||||
|
print(f" [x] Receive: {body}")
|
||||||
|
print(f" [+] Complete: {body}")
|
||||||
|
ch.basic_ack(delivery_tag=method.delivery_tag)
|
||||||
|
|
||||||
|
channel.basic_consume(
|
||||||
|
queue=queue_name, on_message_callback=callback)
|
||||||
|
|
||||||
|
channel.start_consuming()
|
@ -0,0 +1,31 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.basic_qos(prefetch_count=1)
|
||||||
|
|
||||||
|
channel.exchange_declare(exchange='grade_book', exchange_type='fanout')
|
||||||
|
|
||||||
|
result = channel.queue_declare(queue='normal_student', durable=True)
|
||||||
|
|
||||||
|
queue_name = result.method.queue
|
||||||
|
|
||||||
|
channel.queue_bind(exchange='grade_book', queue=queue_name)
|
||||||
|
|
||||||
|
print(' [*] Waiting for tasks. To exit press CTRL+C')
|
||||||
|
|
||||||
|
def callback(ch, method, properties, body):
|
||||||
|
print(f" [x] Receive: {body}")
|
||||||
|
time.sleep(random.randint(2,4))
|
||||||
|
print(f" [+] Complete: {body}")
|
||||||
|
ch.basic_ack(delivery_tag=method.delivery_tag)
|
||||||
|
|
||||||
|
channel.basic_consume(
|
||||||
|
queue=queue_name, on_message_callback=callback)
|
||||||
|
|
||||||
|
channel.start_consuming()
|
25
morozov_vladimir_lab_4/Teacher_student_message/teacher.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.exchange_declare(exchange='grade_book',
|
||||||
|
exchange_type='fanout')
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
while True:
|
||||||
|
count+= 1
|
||||||
|
time.sleep(1)
|
||||||
|
message = f"Homework #{count}"
|
||||||
|
channel.basic_publish(exchange='grade_book',
|
||||||
|
routing_key='',
|
||||||
|
body=message,
|
||||||
|
properties=pika.BasicProperties(
|
||||||
|
delivery_mode=pika.DeliveryMode.Persistent
|
||||||
|
))
|
||||||
|
print(f" [x] Sent {message}")
|
||||||
|
|
BIN
morozov_vladimir_lab_4/lesson_1/img.png
Normal file
After Width: | Height: | Size: 178 KiB |
25
morozov_vladimir_lab_4/lesson_1/receive.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import pika, sys, os
|
||||||
|
|
||||||
|
def main():
|
||||||
|
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.queue_declare(queue='hello')
|
||||||
|
|
||||||
|
def callback(ch, method, properties, body):
|
||||||
|
print(f" [x] Received {body}")
|
||||||
|
|
||||||
|
channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)
|
||||||
|
|
||||||
|
print(' [*] Waiting for messages. To exit press CTRL+C')
|
||||||
|
channel.start_consuming()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('Interrupted')
|
||||||
|
try:
|
||||||
|
sys.exit(0)
|
||||||
|
except SystemExit:
|
||||||
|
os._exit(0)
|
11
morozov_vladimir_lab_4/lesson_1/send.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.queue_declare(queue='hello')
|
||||||
|
|
||||||
|
channel.basic_publish(exchange='', routing_key='hello', body='Hello World!')
|
||||||
|
print(" [x] Sent 'Hello World!'")
|
||||||
|
connection.close()
|
BIN
morozov_vladimir_lab_4/lesson_2/img.png
Normal file
After Width: | Height: | Size: 362 KiB |
18
morozov_vladimir_lab_4/lesson_2/new_task.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import sys
|
||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.queue_declare(queue='task_queue', durable=True)
|
||||||
|
|
||||||
|
message = ' '.join(sys.argv[1:]) or "Hello World!"
|
||||||
|
|
||||||
|
channel.basic_publish(exchange='',
|
||||||
|
routing_key="task_queue",
|
||||||
|
body=message,
|
||||||
|
properties=pika.BasicProperties(
|
||||||
|
delivery_mode = pika.DeliveryMode.Persistent
|
||||||
|
))
|
||||||
|
print(f" [x] Sent {message}")
|
29
morozov_vladimir_lab_4/lesson_2/worker.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
import pika, sys, os
|
||||||
|
|
||||||
|
def main():
|
||||||
|
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
channel.basic_qos(prefetch_count=1)
|
||||||
|
channel.queue_declare(queue='task_queue', durable=True)
|
||||||
|
def callback(ch, method, properties, body):
|
||||||
|
print(f" [x] Received {body.decode()}")
|
||||||
|
time.sleep(body.count(b'.'))
|
||||||
|
print(" [x] Done")
|
||||||
|
ch.basic_ack(delivery_tag=method.delivery_tag)
|
||||||
|
|
||||||
|
channel.basic_consume(queue='task_queue', on_message_callback=callback)
|
||||||
|
|
||||||
|
print(' [*] Waiting for messages. To exit press CTRL+C')
|
||||||
|
channel.start_consuming()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('Interrupted')
|
||||||
|
try:
|
||||||
|
sys.exit(0)
|
||||||
|
except SystemExit:
|
||||||
|
os._exit(0)
|
BIN
morozov_vladimir_lab_4/lesson_3/img.png
Normal file
After Width: | Height: | Size: 148 KiB |
22
morozov_vladimir_lab_4/lesson_3/receiver.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.exchange_declare(exchange='logs', exchange_type='fanout')
|
||||||
|
|
||||||
|
result = channel.queue_declare(queue='', exclusive=True)
|
||||||
|
queue_name = result.method.queue
|
||||||
|
|
||||||
|
channel.queue_bind(exchange='logs', queue=queue_name)
|
||||||
|
|
||||||
|
print(' [*] Waiting for logs. To exit press CTRL+C')
|
||||||
|
|
||||||
|
def callback(ch, method, properties, body):
|
||||||
|
print(f" [x] {body}")
|
||||||
|
|
||||||
|
channel.basic_consume(
|
||||||
|
queue=queue_name, on_message_callback=callback, auto_ack=True)
|
||||||
|
|
||||||
|
channel.start_consuming()
|
20
morozov_vladimir_lab_4/lesson_3/send.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import sys
|
||||||
|
import pika
|
||||||
|
|
||||||
|
connection = pika.BlockingConnection(
|
||||||
|
pika.ConnectionParameters(host='localhost'))
|
||||||
|
channel = connection.channel()
|
||||||
|
|
||||||
|
channel.exchange_declare(exchange='logs',
|
||||||
|
exchange_type='fanout')
|
||||||
|
|
||||||
|
message = ' '.join(sys.argv[1:]) or "Hello World!"
|
||||||
|
|
||||||
|
channel.basic_publish(exchange='logs',
|
||||||
|
routing_key='',
|
||||||
|
body=message,
|
||||||
|
properties=pika.BasicProperties(
|
||||||
|
delivery_mode=pika.DeliveryMode.Persistent
|
||||||
|
))
|
||||||
|
|
||||||
|
print(f" [x] Sent {message}")
|
44
morozov_vladimir_lab_4/readme.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Лабораторная работа №4 - Работа с брокером сообщений
|
||||||
|
|
||||||
|
## Прохождение уроков
|
||||||
|
|
||||||
|
Урок №1.
|
||||||
|
![img.png](lesson_1%2Fimg.png)
|
||||||
|
|
||||||
|
Урок №2.
|
||||||
|
![img.png](lesson_2%2Fimg.png)
|
||||||
|
|
||||||
|
Урок №3.
|
||||||
|
![img.png](lesson_3%2Fimg.png)
|
||||||
|
|
||||||
|
Все приложения были разработаны на Python
|
||||||
|
|
||||||
|
## Разработанные приложения
|
||||||
|
В качестве предметной области было выбрано общение учителя и его учеников. Учитель дает задание ученикам, а они их выполняют. Я выделил 2 вида учеников: обычные, которым нужно некоторое время на то, чтобы выполнить задание; крутые ученики, которые выполняют задание моментально, как только получают его.
|
||||||
|
Были созданы следующие приложения:
|
||||||
|
- teacher - программа, которая представляет учителя и отправляет задания ученикам
|
||||||
|
- Student_Normal - программа, которая представялет обычного ученика, получает и обрабатывает, с задержкой, полученные задания.
|
||||||
|
- Student_Cool - программа, которая представялет крутого ученика, получает и моментально обрабатывает полученные задания.
|
||||||
|
Все программы были разработаны на языке Python.
|
||||||
|
Проведенные тесты:
|
||||||
|
#### Тест №1. Запущены 1 учитель, 1 обычный ученик, 1 крутой ученик:
|
||||||
|
![FirstTest.png](Teacher_student_message%2FFirstTest.png)
|
||||||
|
Показатели очереди обычного ученика:
|
||||||
|
![FirstTest_Normal.png](Teacher_student_message%2FFirstTest_Normal.png)
|
||||||
|
Показатели очереди крутого ученика:
|
||||||
|
![FirstTest_Cool.png](Teacher_student_message%2FFirstTest_Cool.png)
|
||||||
|
|
||||||
|
Вывод: одного обычного ученика не хватает на то, чтобы выполнять все полученные в срок, ему тяжело :(
|
||||||
|
Крутому же ученику все дается с легкостью.
|
||||||
|
|
||||||
|
#### Тест №2. Запущены 1 учитель, 4 обычных ученика:
|
||||||
|
![SecondTest.png](Teacher_student_message%2FSecondTest.png)
|
||||||
|
Показатели очереди обычного ученика:
|
||||||
|
![FirstTest_Normal.png](Teacher_student_message%2FFirstTest_Normal.png)
|
||||||
|
Вывод: если 4 обычных ученика объединяться и будут делать задания вместе, то они смогут избежать переполнения очереди заданий.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Запись тестирования
|
||||||
|
Работа приложения представлена в [видео](https://disk.yandex.ru/i/zzwvXXpZhavh7A)
|