Compare commits

..

3 Commits

Author SHA1 Message Date
022e2dc49e + 2024-10-08 23:46:12 +04:00
a54e13f7ee + 2024-10-08 23:45:00 +04:00
1bb988ea2f dozorova_alena_lab_6 2024-10-08 23:43:24 +04:00
18 changed files with 198 additions and 442 deletions

View File

@@ -7,3 +7,6 @@
/dozorova_alena_lab_2/ConsoleApp2/.vs
/dozorova_alena_lab_2/ConsoleApp2/bin
/dozorova_alena_lab_2/ConsoleApp2/obj
/dozorova_alena_lab_6/ConsoleApp1/.vs
/dozorova_alena_lab_6/ConsoleApp1/bin
/dozorova_alena_lab_6/ConsoleApp1/obj

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35004.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1.csproj", "{29269567-7466-4C99-BEEF-F5766BDDFB24}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{29269567-7466-4C99-BEEF-F5766BDDFB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29269567-7466-4C99-BEEF-F5766BDDFB24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29269567-7466-4C99-BEEF-F5766BDDFB24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29269567-7466-4C99-BEEF-F5766BDDFB24}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EDED6E1D-0A86-43F9-94EA-6ADCC1FA1B42}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public static class Extention
{
public static int[,] CreateMatrixWithoutColumn(this int[,] matrix, int column)
{
var result = new int[matrix.GetLength(0), matrix.GetLength(1) - 1];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1) - 1; j++)
{
result[i, j] = j < column ? matrix[i, j] : matrix[i, j + 1];
}
}
return result;
}
public static int[,] CreateMatrixWithoutRow(this int[,] matrix, int row)
{
var result = new int[matrix.GetLength(0) - 1, matrix.GetLength(1)];
for (int i = 0; i < matrix.GetLength(0) - 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
result[i, j] = i < row ? matrix[i, j] : matrix[i + 1, j];
}
}
return result;
}
public static double CalculateDeterminant(this int[,] matrix)
{
if (matrix.GetLength(0) == 2)
{
return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0];
}
double result = 0;
for (var j = 0; j < matrix.GetLength(0); j++)
{
result += (j % 2 == 1 ? 1 : -1) * matrix[1, j] *
matrix.CreateMatrixWithoutColumn(j).CreateMatrixWithoutRow(1).CalculateDeterminant();
}
//Console.WriteLine("Ко мне пришли с размером " + matrix.GetLength(0));
return result;
}
}
}

View File

@@ -0,0 +1,87 @@

using ConsoleApp1;
using System.Data.Common;
using System.Diagnostics;
internal class Program
{
private static void Main(string[] args)
{
var value = new int[3] {100, 300, 500 };
foreach(var i in value)
{
var a = CreateMatrix(i, i);
var b = CreateMatrix(i, i);
List<long> times = new() {};
Console.WriteLine("Для пяти потоков: ");
for (int j = 1; j <= 10; j++)
{
var sw = new Stopwatch();
sw.Start();
Calculate(a, j);
sw.Stop();
times.Add(sw.ElapsedTicks);
}
Console.WriteLine("Количество тиков для вычисления матрицы стороной "+i+": "+string.Join("\t", times));
Console.WriteLine("Для десяти потоков: ");
for (int j = 1; j <= 10; j++)
{
var sw = new Stopwatch();
sw.Start();
Calculate(a, j);
sw.Stop();
times.Add(sw.ElapsedTicks);
}
Console.WriteLine("Количество тиков для вычисления матрицы стороной " + i + ": " + string.Join("\t", times));
}
}
private static int[,] CreateMatrix(int x, int y)
{
var rnd = new Random();
var res = new int[y, x];
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
res[i, j] = rnd.Next(0, 100);
}
}
return res;
}
private static double Calculate(int[,] matrix, int maxTask)
{
double res = 0;
var semaphore = new SemaphoreSlim(maxTask, maxTask);
for (var j = 0; j < matrix.GetLength(0) - 1; j++)
{
_ = Task.Run(() =>
{
try
{
semaphore.Wait();
res += (j % 2 == 1 ? 1 : -1) * matrix[1, j] *
matrix.CreateMatrixWithoutColumn(j).
CreateMatrixWithoutRow(1).CalculateDeterminant();
}
finally { semaphore.Release(); }
});
}
semaphore.Wait(maxTask);
return res;
}
}

View File

@@ -0,0 +1,18 @@
# Лабораторная работа 6
В рамках данной работы мы изучаем выигрыш при распаралелливании процесса вычисления определителя матрицы
## Описание
Для вычисления определителя мы используем следующую формулу:
![alt text](image.png)
где ![alt text](image-1.png) - определитель матрицы, полученной из исходной вырезанием 1 строки и j столбца.
## Запуск
По опыту прошлой лабораторной работы, в консольном приложении был реализован алгоритм вычисление детерминанта и запущено сравнение затраченного времени (в тиках) для 5 и 10 потоков.
## Результаты
Результаты:
<br/>
![Результат](image-2.png)
<br/>
Как мы видим, подтверждаются выводы прошлой лабораторной работы: для небольших матриц выигрыш несущественнен из-за затраты времени на работу с потоком, а для больших эта разница в скорости уже существенна
## Видеодемонстрация
Видеодемонстрация по [адресу](https://drive.google.com/file/d/1LFRNbTAOzg21Du60Ehy9u6HOp9D3sKPm/view?usp=sharing)

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,64 +0,0 @@
# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами
## Задание
#### Цель:
Изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API.
#### Задачи:
* Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
* Реализовать механизм синхронного обмена сообщениями между микросервисами.
* Реализовать шлюз на основе прозрачного прокси-сервера nginx.
### Сервисы:
&nbsp;1. ```product_server``` - сервис, отвечающий за продукты
&nbsp;2. ```document_server``` - сервис, отвечающий за документы, которые содержат в себе продукты
#### Связь между сервисами:
```document (single) <- product (many)```
## Как запустить программу:
```
docker compose up
```
## Файловая иерархия
```
Лаба 3/
|-- document_server/
| |-- Dockerfile
| |-- document_server.py
|-- product_server/
| |-- Dockerfile
| |-- product_server.py
|-- nginx.conf
|-- docker-compose.yml
|-- requirements.txt
|-- Test_commands.txt
```
## Описание работы:
Для разработки приложений был выбран язык программирования - ```python```
#### Синхронный обмен сообщениями
`product_server` будет отправлять http-запрос на `document_server` при определенных crud операциях.
### Docker-compose
Конфигурационный файл ```docker-сompose``` представляет собой многоконтейнерное приложение с тремя сервисами: ```product_server```, ```document_server``` и ```nginx```. Обязанности маршрутизатора возложены на сервер Nginx
### Nginx
Этот файл представляет собой конфигурацию для ```Nginx```, который является веб-сервером и обратным прокси.
# ВК
https://vk.com/video256017065_456239873

View File

@@ -1,24 +0,0 @@
http://document_server:8008/documents/all/ - get
http://document_server:8008/documents/9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0 - get
http://document_server:8008/documents/full/9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0 - get
http://document_server:8008/documents/ - post
title content manager
http://document_server:8008/ - /documents/9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0 title ПРОВЕРКА manager ПОЛЬЗОВАТЕЛЬ МЕНЕДЖЕР
http://document_server:8008documents/9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0
http://product_server:8009/products/all/ - get
http://product_server:8009/products/085a7833-e486-4a55-9289-d253e21fe64e - get
http://product_server:8009/products/full/085a7833-e486-4a55-9289-d253e21fe64e - get
http://product_server:8009/products/list/documents/4a3f30c3-823f-4278-8f98-76177ad083bd - get
http://product_server:8009/products/ - post
name price uuid_document
http://product_server:8009/products/085a7833-e486-4a55-9289-d253e21fe64e - put
http://product_server:8009/products/085a7833-e486-4a55-9289-d253e21fe64e - delete

View File

@@ -1,27 +0,0 @@
services:
document_server:
container_name: document_server
build:
context: .
dockerfile: ./document_server/Dockerfile
expose:
- 8008
product_server:
container_name: product_server
build:
context: .
dockerfile: ./product_server/Dockerfile
expose:
- 8009
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- document_server
- product_server

View File

@@ -1,17 +0,0 @@
# Использую базовый образ Python
FROM python:3.10-slim
# Устанавливаю рабочую директорию внутри контейнера
WORKDIR /app
# Копирую файл requirements.txt в контейнер
COPY requirements.txt .
# Устанавливаю зависимости
RUN pip install --no-cache-dir -r requirements.txt
# Копирую исполняемый файл
COPY document_server/main.py .
# Команда для запуска Python-скрипта
CMD ["python", "main.py"]

View File

@@ -1,115 +0,0 @@
from fastapi import FastAPI, HTTPException
from fastapi.responses import RedirectResponse
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
from uuid import UUID, uuid4
import requests
app = FastAPI(title="Document service")
product_url = 'http://product_server:8009'
# Добавили автогенерацию уникального идентификатора
class Document(BaseModel):
uuid_: UUID = Field(default_factory=uuid4)
title: str | None
content: str | None
manager: str | None
# Наше хранилище данных
# Пару id указываем явно, остальные генерируются случайно
DATA_LIST: list[Document] = [
Document(uuid_="4a3f30c3-823f-4278-8f98-76177ad083bd", title="Document 1", content="Content 1", manager="Manager 1"),
Document(uuid_="9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0", title="Document 2", content="Content 2", manager="Manager 2"),
Document(title="Document 3", content="Content 3", manager="Manager 3"),
Document(title="Document 4", content="Content 4", manager="Manager 4"),
]
@app.get("/")
async def redirect_to_docs():
return RedirectResponse(url="/docs")
@app.get("/documents/all/", tags=["Document"])
def all_documents():
return DATA_LIST
@app.get("/documents/{document_id}", tags=["Document"])
def get_document(document_id: UUID):
document = next((x for x in DATA_LIST if x.uuid_ == document_id), None)
if not document:
return HTTPException(status_code=404, detail="Документ не найден")
return document
@app.get("/documents/full/{document_id}", tags=["Document"])
def get_full_document(document_id: UUID):
document = next((x for x in DATA_LIST if x.uuid_ == document_id), None)
if not document:
return HTTPException(status_code=404, detail="Продукт не найден")
result_dict = document.model_dump()
if type(result_dict['uuid_']) is UUID:
products = requests.get(f"{product_url}/products/list/documents/{document_id}")
if not products:
return HTTPException(status_code=404, detail="Продукты не найдены")
result_dict["products"] = products.json()
return result_dict
@app.post("/documents/", tags=["Document"])
def create_document(title: str, content: str, manager: str):
document = Document(title=title, content=content, manager=manager)
try:
DATA_LIST.append(document)
return JSONResponse(content={"message": "Успешное создание документа"}, status_code=200)
except Exception as e:
return HTTPException(status_code=404, detail={"Неудачная попытка добавления документа": str(e)})
@app.put("/documents/{document_id}", tags=["Document"])
def update_document(document_id: UUID, title: str = None, content: str = None, manager: str = None):
document = get_document(document_id)
if type(document) is Document:
index = DATA_LIST.index(document)
if title:
DATA_LIST[index].title = title
if content:
DATA_LIST[index].content = content
if manager:
DATA_LIST[index].manager = manager
return JSONResponse(content={"message": "Успешное обновление документа"}, status_code=201)
else:
return HTTPException(status_code=404, detail=document)
@app.delete("/documents/{document_id}", tags=["Document"])
def delete_document(document_id: UUID):
document = get_document(document_id)
if type(document) is Document:
index = DATA_LIST.index(document)
print(index)
del DATA_LIST[index]
return JSONResponse(content={"message": "Успешное удаление документа"}, status_code=201)
return HTTPException(status_code=404, detail=document)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8008)

View File

@@ -1,25 +0,0 @@
events { worker_connections 1024; }
http {
server {
listen 80;
listen [::]:80;
server_name localhost;
location /document_server/ {
proxy_pass http://document_server:8008/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /product_server/ {
proxy_pass http://product_server:8009/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

View File

@@ -1,17 +0,0 @@
# Использую базовый образ Python
FROM python:3.10-slim
# Устанавливаю рабочую директорию внутри контейнера
WORKDIR /app
# Копирую файл requirements.txt в контейнер
COPY requirements.txt .
# Устанавливаю зависимости
RUN pip install --no-cache-dir -r requirements.txt
# Копирую исполняемый файл
COPY product_server/main.py .
# Команда для запуска Python-скрипта
CMD ["python", "main.py"]

View File

@@ -1,136 +0,0 @@
from fastapi import FastAPI, HTTPException
from fastapi.responses import RedirectResponse
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
from uuid import UUID, uuid4
import requests
app = FastAPI(title="Product service")
document_url = 'http://document_server:8008'
# Добавили автогенерацию уникального идентификатора
class Product(BaseModel):
uuid_: UUID = Field(default_factory=uuid4)
name: str | None
price: int | None
uuid_document: UUID | None
# Наше хранилище данных
DATA_LIST: list[Product] = [
Product(uuid_="085a7833-e486-4a55-9289-d253e21fe64e",name="Товар 1", price=100, uuid_document="4a3f30c3-823f-4278-8f98-76177ad083bd"),
Product(name="Товар 2", price=200, uuid_document="4a3f30c3-823f-4278-8f98-76177ad083bd"),
Product(name="Товар 3", price=300, uuid_document="9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0"),
Product(name="Товар 4", price=400, uuid_document="9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0"),
Product(name="Товар 5", price=500, uuid_document="9c7f1ecb-1aac-4337-bcd0-f863cc73aeb0"),
]
@app.get("/")
async def redirect_to_docs():
return RedirectResponse(url="/docs")
@app.get("/products/all/", tags=["Product"])
def all_products():
return DATA_LIST
@app.get("/products/{product_id}", tags=["Product"])
def get_product(product_id: UUID):
product = next((x for x in DATA_LIST if x.uuid_ == product_id), None)
if not product:
return HTTPException(status_code=404, detail="Продукт не найден")
return product
@app.get("/products/full/{product_id}", tags=["Product"])
def get_full_product(product_id: UUID):
product = next((x for x in DATA_LIST if x.uuid_ == product_id), None)
if not product:
return HTTPException(status_code=404, detail="Продукт не найден")
result_dict = product.model_dump()
if type(result_dict['uuid_document']) is UUID:
document = requests.get(f"{document_url}/documents/{result_dict['uuid_document']}")
if not document:
return HTTPException(status_code=404, detail="Документ не найден")
result_dict["document"] = document.json()
del result_dict['uuid_document']
return result_dict
@app.get("/products/list/documents/{document_id}", tags=["Product"])
def get_list_product_document(document_id: UUID):
products = (x for x in DATA_LIST if x.uuid_document == document_id)
if not products:
return HTTPException(status_code=404, detail="Продукты не найдены")
return products
@app.get("/products/{product_id}", tags=["Product"])
def get_product(product_id: UUID):
product = next((x for x in DATA_LIST if x.uuid_ == product_id), None)
if not product:
return HTTPException(status_code=404, detail="Продукт не найден")
return product
@app.post("/products/", tags=["Product"])
def create_product(name: str, price: int, uuid_document: UUID):
product = Product(name=name, price=price, uuid_document=uuid_document)
try:
DATA_LIST.append(product)
return JSONResponse(content={"message": "Успешное создание продукта"}, status_code=200)
except Exception as e:
return HTTPException(status_code=404, detail={"Неудачная попытка добавления продукта": str(e)})
@app.put("/products/{product_id}", tags=["Product"])
def update_product(product_id: UUID, name: str = None, price: int = None, uuid_document: UUID = None):
product = get_product(product_id)
if type(product) is Product:
index = DATA_LIST.index(product)
if name:
DATA_LIST[index].name = name
if price:
DATA_LIST[index].price = price
if uuid_document:
DATA_LIST[index].uuid_document = uuid_document
return JSONResponse(content={"message": "Успешное обновление продукта"}, status_code=201)
else:
return HTTPException(status_code=404, detail=product)
@app.delete("/products/{product_id}", tags=["Product"])
def delete_product(product_id: UUID):
product = get_product(product_id)
if type(product) is Product:
index = DATA_LIST.index(product)
print(index)
del DATA_LIST[index]
return JSONResponse(content={"message": "Успешное удаление продукта"}, status_code=201)
return HTTPException(status_code=404, detail=product)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8009)

View File

@@ -1,17 +0,0 @@
annotated-types==0.7.0
anyio==4.6.0
certifi==2024.8.30
charset-normalizer==3.4.0
click==8.1.7
exceptiongroup==1.2.2
fastapi==0.115.0
h11==0.14.0
idna==3.10
pydantic==2.9.2
pydantic_core==2.23.4
requests==2.32.3
sniffio==1.3.1
starlette==0.38.6
typing_extensions==4.12.2
urllib3==2.2.3
uvicorn==0.31.0