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 353 deletions

View File

@@ -1,2 +0,0 @@
/.idea
/.venv

View File

@@ -1,22 +0,0 @@
# Лабораторная работа №3
## Богданов Дмитрий ПИбд-42
### Для выполнения были выбраны следующие сущности:
* Message - содержит uuid (генерируется), text, datetime_sent, user_id
* User - содержит uuid (генерируется), name, surname
Одному пользователю может быть присвоено несколько сообщений.
Соответственно были развернуты 2 сервиса для управления этими сущностями.
### Запуск лабораторной:
Необходимо перейти в папку с файлом compose.yaml и ввести следующую команду:
```
docker-compose up --build -d
```
## Видео с результатом запуска и тестами...
...можно посмотреть по данной [ссылке](https://drive.google.com/file/d/1cJz0z4KduSz1oltmAuieUW7GxxVLNPNo/view).

View File

@@ -1,27 +0,0 @@
services:
user_service:
container_name: userService
build:
context: .
dockerfile: ./userService/Dockerfile
expose:
- 20001
message_service:
container_name: messageService
build:
context: .
dockerfile: ./messageService/Dockerfile
expose:
- 20002
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- user_service
- message_service

View File

@@ -1,11 +0,0 @@
FROM python:latest
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY messageService/messageService.py .
CMD ["python", "messageService.py"]

View File

@@ -1,138 +0,0 @@
from flask import Flask, request, jsonify
from uuid import uuid4
import uuid
import datetime
import requests
class Message:
def __init__(self, text: str, datetime_sent: datetime, uuid_: uuid, user_id: uuid):
if uuid_ is None:
self.uuid_ = uuid4()
else:
self.uuid_ = uuid.UUID(uuid_)
self.text = text
self.datetime_sent = datetime_sent
self.user_id = uuid.UUID(user_id)
def to_dict(self):
return {
'text': self.text,
'datetime_sent': self.datetime_sent,
'user_id': self.user_id,
'uuid': self.uuid_
}
def to_dict_for_users(self):
return {
'title': self.text,
'datetime_sent': self.datetime_sent,
'uuid': self.uuid_
}
def to_dict_with_info(self, user: dict):
return {
'title': self.text,
'datetime_sent': self.datetime_sent,
'user_id': self.user_id,
'user_info': user,
'uuid': self.uuid_
}
messages = [
Message(text='Hi!', datetime_sent=datetime.datetime.now(), uuid_='4add0525-1857-477d-ad35-56790d400b72', user_id='94b171ea-39f6-4a67-9c67-061743f67cfd'),
Message(text='Hello this is a message', datetime_sent=datetime.datetime.now(), uuid_='dd69758d-89e8-49b5-86bf-54ae2adb64e8', user_id='724a3192-70dd-4909-9b0f-c9060a4ab1bd'),
Message(text='Test', datetime_sent=datetime.datetime.now(), uuid_='92389e8d-4365-457e-b37e-78abbc07f194', user_id='94b171ea-39f6-4a67-9c67-061743f67cfd'),
Message(text='Anyone here?', datetime_sent=datetime.datetime.now(), uuid_='f3a1c526-aca2-47e2-afd3-a1c2eac92458', user_id='724a3192-70dd-4909-9b0f-c9060a4ab1bd'),
Message(text='Mambo', datetime_sent=datetime.datetime.now(), uuid_='00abbdb5-e480-4842-bc32-f916894757eb', user_id='46672ea5-3d7b-4137-a0ac-efd898ca4db6')
]
def list_jsonify():
return jsonify([message.to_dict() for message in messages])
app = Flask(__name__)
users_url = 'http://userService:20001/'
@app.route('/', methods=['GET'])
def get_all():
return list_jsonify(), 200
@app.route('/info', methods=['GET'])
def get_all_full():
users: list[dict] = requests.get(users_url).json()
response = []
for message in messages:
for user in users:
if message.user_id == uuid.UUID(user.get('uuid')):
response.append(message.to_dict_with_info(user))
return response, 200
@app.route('/by-user/<uuid:user_uuid>', methods=['GET'])
def get_by_user_id(user_uuid):
return [message.to_dict_for_users() for message in messages if message.user_id == user_uuid], 200
@app.route('/info/<uuid:uuid_>', methods=['GET'])
def get_one_full(uuid_):
for message in messages:
if message.uuid_ == uuid_:
response = requests.get(users_url + str(message.user_id))
return message.to_dict_with_info(response.json()), 200
return f'Сообщение с uuid {uuid_} не найдено', 404
@app.route('/', methods=['POST'])
def create():
data = request.json
text = data.get('text', None)
datetime_sent = datetime.datetime.now()
user_id = data.get('user_id', None)
checking = requests.get(users_url + f'/check/{user_id}')
print(checking)
if checking.status_code == 200:
new_message = Message(text, datetime_sent, None, user_id)
messages.append(new_message)
return get_one(new_message.uuid_)
if checking.status_code == 404:
return f'Пользователь с uuid {user_id} не существует', 404
return 'Неизвестная ошибка', 500
@app.route('/<uuid:uuid_>', methods=['PUT'])
def update_by_id(uuid_):
data = request.json
new_text = data.get('text', None)
for message in messages:
print(message.uuid_)
if message.uuid_ == uuid_:
if new_text is not None:
message.text = new_text
return get_one(message.uuid_)
return f'Сообщение с uuid {uuid_} не найдено', 404
@app.route('/<uuid:uuid_>', methods=['DELETE'])
def delete(uuid_):
for message in messages:
if message.uuid_ == uuid_:
messages.remove(message)
return 'Сообщение успешно удалено', 200
return f'Сообщение с uuid {uuid_} не найдено', 404
@app.route('/<uuid:uuid_>', methods=['GET'])
def get_one(uuid_):
for message in messages:
if message.uuid_ == uuid_:
return message.to_dict(), 200
return f'Сообщение с uuid {uuid_} не найдено', 404
if __name__ == '__main__':
app.run(host='0.0.0.0', port=20002, debug=True)

View File

@@ -1,25 +0,0 @@
events { worker_connections 1024; }
http {
server {
listen 80;
listen [::]:80;
server_name localhost;
location /userService/ {
proxy_pass http://userService:20001/;
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 /messageService/ {
proxy_pass http://messageService:20002/;
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,2 +0,0 @@
Flask==3.0.3
requests==2.32.3

View File

@@ -1,11 +0,0 @@
FROM python:latest
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY userService/userService.py .
CMD ["python", "userService.py"]

View File

@@ -1,115 +0,0 @@
from flask import Flask, jsonify, request
from uuid import uuid4
import uuid
import requests
class User:
def __init__(self, name, surname, uuid_: uuid):
if uuid_ is None:
self.uuid_: uuid = uuid4()
else:
self.uuid_: uuid = uuid.UUID(uuid_)
self.name: str = name
self.surname: str = surname
def to_dict(self):
return {
"uuid": self.uuid_,
"name": self.name,
"surname": self.surname
}
def to_dict_with_messages(self, messages: list):
return {
"uuid": self.uuid_,
"name": self.name,
"surname": self.surname,
"messages": messages
}
app = Flask(__name__)
users: list[User] = [
User(name='Dr.', surname='Kino', uuid_='94b171ea-39f6-4a67-9c67-061743f67cfd'),
User(name='Caspian', surname='Holstrom', uuid_='724a3192-70dd-4909-9b0f-c9060a4ab1bd'),
User(name='Admin', surname='Admin', uuid_='46672ea5-3d7b-4137-a0ac-efd898ca4db6')
]
messages_url = 'http://messageService:20002/'
def list_jsonify():
return jsonify([user.to_dict() for user in users])
@app.route('/', methods=['GET'])
def get_all():
return list_jsonify(), 200
@app.route('/<uuid:uuid_>', methods=['GET'])
def get_one(uuid_):
for user in users:
if user.uuid_ == uuid_:
return user.to_dict(), 200
return f'Пользователь с uuid {uuid_} не найден', 404
@app.route('/info/<uuid:uuid_>', methods=['GET'])
def get_one_with_messages(uuid_):
for user in users:
if user.uuid_ == uuid_:
response = requests.get(messages_url + f'by-user/{uuid_}')
print(response.json())
return user.to_dict_with_messages(response.json()), 200
return f'Пользователь с uuid {uuid_} не найден', 404
@app.route('/check/<uuid:uuid_>', methods=['GET'])
def check_exist(uuid_):
for user in users:
if user.uuid_ == uuid_:
return '', 200
return '', 404
@app.route('/', methods=['POST'])
def create():
data = request.json
name = data.get('name', None)
surname = data.get('surname', None)
if name is None or surname is None:
return 'Недостаточно информации для создания пользователя', 404
new_user = User(name, surname, None)
users.append(new_user)
return get_one(new_user.uuid_)
@app.route('/<uuid:uuid_>', methods=['PUT'])
def update_by_id(uuid_):
data = request.json
new_name = data.get('name', None)
new_surname = data.get('surname', None)
for user in users:
if user.uuid_ == uuid_:
if new_name is not None:
user.name = new_name
if new_surname is not None:
user.surname = new_surname
return get_one(user.uuid_)
return f'Пользователь с uuid {uuid_} не найден', 404
@app.route('/<uuid:uuid_>', methods=['DELETE'])
def delete(uuid_):
for user in users:
if user.uuid_ == uuid_:
users.remove(user)
return 'Пользователь удален', 200
return f'Пользователь с uuid {uuid_} не найден', 404
if __name__ == '__main__':
app.run(host='0.0.0.0', port=20001, debug=True)

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