1 Commits

Author SHA1 Message Date
73a33347fe Lab_5 2023-12-18 17:45:19 +04:00
35 changed files with 138 additions and 588 deletions

View File

@@ -1,83 +0,0 @@
# Отчёт по лабораторной работе №3
Выполнила: студентка гр. ИСЭбд-41 Никифорова Татьяна Сергеевна.
## REST API, Gateway и синхронный обмен между микросервисами
## Создание микросервисов
Использовала команду `dotnet new web -n worker-1` в терминале для создания моего первого микросервиса.
Далее, с помощью команды `dotnet new sln`, создала решение для проекта. Затем использовала команду `dotnet sln worker-1.sln add worker-1.csproj`, чтобы связать созданное решение с проектом.
Повторила те же действия для второго микросервиса, добавила оба проекта в единое решение.
Добавил библиотеку Swagger и OpenAi в проекты и запустил с помощью команды `dotnet run`".
Скриншоты API приложений:
![](picture/sworker-1.png)
![](picture/sworker-2.png)
## Реализация синхронного обмена
Реализовала механизм синхронного обмена сообщениями между микросервисами.
```cs
app.MapGet("/Authors/", async () =>
{
var httpClient = new HttpClient();
var secondWorkerResponse = await httpClient.GetStringAsync("http://worker-1:8080/");
return secondWorkerResponse.ToArray();
})
.WithName("GetRequests")
.WithOpenApi();
```
## Реализация gateway при помощи nginx
Реализовала шлюз на основе прозрачного прокси-сервера nginx.
```conf
server {
listen 8080;
listen [::]:8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /worker-1/ {
proxy_pass http://worker-1:8080/;
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-Prefix /worker-1;
}
location /worker-2/ {
proxy_pass http://worker-2:8080/;
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-Prefix /worker-2;
}
}
```
Результаты, после вызова команды `docker-compose up`:
Docker Desktop:
![](picture/docker.png)
index.html на gateway-1:
![](picture/test.png)
worker-1:
![](picture/lworker-1.png)
worker-2:
![](picture/lworker-2.png)

View File

@@ -1,15 +0,0 @@
version: "3.1"
services:
worker-1:
build: ./worker-1
worker-2:
build: ./worker-2
depends_on:
- worker-1
gateway:
image: nginx:latest
ports:
- 8080:8080
volumes:
- ./static:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro

View File

@@ -1,26 +0,0 @@
server {
listen 8080;
listen [::]:8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /worker-1/ {
proxy_pass http://worker-1:8080/;
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-Prefix /worker-1;
}
location /worker-2/ {
proxy_pass http://worker-2:8080/;
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-Prefix /worker-2;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Лабараторная работа №3</title>
</head>
<body>
<p>Никифорова Татьяна С. студентка ИСЭбд-41.</p>
<p><a href="/worker-1/">Запрос к "worker-1"</a></p>
<p><a href="/worker-2/">Запрос к "worker-2"</a></p>
</body>
</html>

View File

@@ -1,11 +0,0 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /app
COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "worker-1.dll"]

View File

@@ -1,118 +0,0 @@
List<Books > books = new()
{
new Books () { Uuid= Guid.Parse("6a1b4a72-5669-41fe-8d5b-106dc86f58bd"), Title = "Programming Basics", Genre = "Programming" },
new Books () { Uuid= Guid.Parse("464bbdb8-39c0-4644-b9c0-3df1c484ea7e"), Title = "Advanced Algorithms", Genre = "Programming" },
new Books () { Uuid= Guid.Parse("f8692bea-b7e6-4164-b564-a921f16c35c9"), Title = "Romantic Journey", Genre = "Romance" },
};
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/", () =>
{
return books.Select(r => new BookEntityDto()
{
Uuid = r.Uuid,
Title = r.Title,
Genre = r.Genre,
});
})
.WithName("GetBooks")
.WithOpenApi();
app.MapGet("/{uuid}", (Guid uuid) =>
{
var book = books.FirstOrDefault(r => r.Uuid == uuid);
if (book == null)
return Results.NotFound();
return Results.Json(new BookEntityDto()
{
Uuid = book.Uuid,
Title = book.Title,
Genre = book.Genre,
});
})
.WithName("GetBookByGUID")
.WithOpenApi();
app.MapPost("/{title}/{genre}", (string title, string genre) =>
{
Guid NewGuid = Guid.NewGuid();
books.Add(new Books() { Uuid = NewGuid, Title = (string)title, Genre = (string)genre});
var book = books.FirstOrDefault(r => r.Uuid == NewGuid);
if (book == null)
return Results.NotFound();
return Results.Json(new BookEntityDto()
{
Uuid = book.Uuid,
Title = book.Title,
Genre = book.Genre,
});
})
.WithName("PostBook")
.WithOpenApi();
app.MapPatch("/{uuid}/{title}/{genre}", (Guid uuid, string ?title, string ?genre) =>
{
var book = books.FirstOrDefault(r => r.Uuid == uuid);
if (book == null)
return Results.NotFound();
if (title != null) book.Title = title;
if (genre != ",") book.Genre = genre;
return Results.Json(new BookEntityDto()
{
Uuid = book.Uuid,
Title = book.Title,
Genre = book.Genre,
});
})
.WithName("UpdateBook")
.WithOpenApi();
app.MapDelete("/{uuid}", (Guid uuid) =>
{
var book = books.FirstOrDefault(r => r.Uuid == uuid);
if (book == null)
return Results.NotFound();
books.Remove(book);
return Results.Json(new BookEntityDto()
{
Uuid = book.Uuid,
Title = book.Title,
Genre = book.Genre,
});
})
.WithName("DeleteBookByGUID")
.WithOpenApi();
app.Run();
public class Books
{
public Guid Uuid { get; set; }
public string Title { get; set; } = string.Empty;
public string Genre { get; set; } = string.Empty;
}
public class BookEntityDto : Books { }

View File

@@ -1,37 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:28800",
"sslPort": 44397
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5108",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7126;http://localhost:5108",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -1,10 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>worker_1</RootNamespace>
</PropertyGroup>
</Project>

View File

@@ -1,22 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-1", "worker-1.csproj", "{AEF383BD-8E80-4FF5-A579-1B601B7D1464}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AEF383BD-8E80-4FF5-A579-1B601B7D1464}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEF383BD-8E80-4FF5-A579-1B601B7D1464}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEF383BD-8E80-4FF5-A579-1B601B7D1464}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEF383BD-8E80-4FF5-A579-1B601B7D1464}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -1,11 +0,0 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /app
COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "worker-2.dll"]

View File

@@ -1,139 +0,0 @@
List<Authors> authors = new()
{
new Authors() { Uuid= Guid.NewGuid(), Number = "1", Name = "Programming Basics", IdBook = Guid.Parse("6a1b4a72-5669-41fe-8d5b-106dc86f58bd") },
new Authors() { Uuid= Guid.NewGuid(), Number = "2", Name = "Advanced Algorithms", IdBook = Guid.Parse("f8692bea-b7e6-4164-b564-a921f16c35c9") },
new Authors() { Uuid= Guid.NewGuid(), Number = "3", Name = "Romantic Journey", IdBook = Guid.Parse("464bbdb8-39c0-4644-b9c0-3df1c484ea7e") },
new Authors() { Uuid= Guid.NewGuid(), Number = "3А", Name = "Mystery Island", IdBook = Guid.Parse("464bbdb8-39c0-4644-b9c0-3df1c484ea7e") },
};
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/", () =>
{
return authors.Select(r => new AuthorEntityDto()
{
Uuid = r.Uuid,
Number = r.Number,
Name = r.Name,
IdBook = r.IdBook,
});
})
.WithName("GetAuthors")
.WithOpenApi();
app.MapGet("/{uuid}", (Guid uuid) =>
{
var author = authors.FirstOrDefault(r => r.Uuid == uuid);
if (author == null)
return Results.NotFound();
return Results.Json(new AuthorEntityDto()
{
Uuid = author.Uuid,
Number = author.Number,
Name = author.Name,
IdBook = author.IdBook,
});
})
.WithName("GetAuthorByGUID")
.WithOpenApi();
app.MapPost("/{number}/{name}/{IdBook}", (string? Number, string Name, Guid IdBook) =>
{
Guid NewGuid = Guid.NewGuid();
authors.Add(new Authors() { Uuid = NewGuid, Number = (string)Number, Name = (string)Name, IdBook = (Guid)IdBook });
var author = authors.FirstOrDefault(r => r.Uuid == NewGuid);
if (author == null)
return Results.NotFound();
return Results.Json(new AuthorEntityDto()
{
Uuid = author.Uuid,
Number = author.Number,
Name = author.Name,
IdBook = author.IdBook,
});
})
.WithName("PostAuthor")
.WithOpenApi();
app.MapPatch("/{uuid}/{number}/{name}/{IdBook}", (Guid uuid, string ?number, string name, Guid IdBook) =>
{
var author = authors.FirstOrDefault(r => r.Uuid == uuid);
if (author == null)
return Results.NotFound();
if (number != ",") author.Number = number;
if (name != author.Name) author.Name = name;
if (IdBook != author.IdBook) author.IdBook = IdBook;
return Results.Json(new AuthorEntityDto()
{
Uuid = author.Uuid,
Number = author.Number,
Name = author.Name,
IdBook = author.IdBook,
});
})
.WithName("UpdateAuthor")
.WithOpenApi();
app.MapDelete("/{uuid}", (Guid uuid) =>
{
var author = authors.FirstOrDefault(r => r.Uuid == uuid);
if (author == null)
return Results.NotFound();
authors.Remove(author);
return Results.Json(new AuthorEntityDto()
{
Uuid = author.Uuid,
Number = author.Number,
Name = author.Name,
IdBook = author.IdBook,
});
})
.WithName("DeleteAuthor")
.WithOpenApi();
app.MapGet("/Authors/", async () =>
{
var httpClient = new HttpClient();
var secondWorkerResponse = await httpClient.GetStringAsync("http://worker-1:8080/");
return secondWorkerResponse.ToArray();
})
.WithName("GetBooks")
.WithOpenApi();
app.Run();
public class Authors
{
public Guid Uuid { get; set; }
public string Number { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public Guid IdBook { get; set; }
}
public class AuthorEntityDto : Authors { }
public class Books
{
public Guid Uuid { get; set; }
public string Title { get; set; } = string.Empty;
public string Genre { get; set; } = string.Empty;
}
public class BookEntityDto : Books { }

View File

@@ -1,37 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:24157",
"sslPort": 44320
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5082",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7130;http://localhost:5082",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -1,10 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>worker_2</RootNamespace>
</PropertyGroup>
</Project>

View File

@@ -1,22 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-2", "worker-2.csproj", "{46EE043B-ED4D-44D1-82AF-3A180AD32532}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46EE043B-ED4D-44D1-82AF-3A180AD32532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46EE043B-ED4D-44D1-82AF-3A180AD32532}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46EE043B-ED4D-44D1-82AF-3A180AD32532}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46EE043B-ED4D-44D1-82AF-3A180AD32532}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,38 @@
# Отчёт по лабораторной работе №5
Выполнила: студентка гр. ИСЭбд-41 Никифорова Татьяна Сергеевна.
## Создание приложения
Выбрала язык Python.
Запустим алгоритм с матрицей 10x10 c различными алгоритмами.
![](picture/1.png)
![](picture/2.png)
## Бенчмарки
Протекстируем обычный и паралелльный с различными размерами матриц.
Матрица 100х100
![](picture/3-100.png)
![](picture/4.png)
Матрица 300х300
![](picture/5-300.png)
![](picture/6.png)
Матрица 500х500
![](picture/7-500.png)
![](picture/8.png)
Вывод: Для небольших матриц и с небольшим количеством ядер процессора параллельная реализация может не всегда оказаться быстрее из-за дополнительных накладных расходов.

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File

@@ -0,0 +1,100 @@
import numpy as np
import tkinter as tk
from tkinter import ttk
from multiprocessing import Pool
import time
def multiply_matrices_sequential(matrix_a, matrix_b):
return np.dot(matrix_a, matrix_b)
def multiply_matrices_parallel(args):
row, matrix_a, matrix_b, cols = args
return [sum(matrix_a[row, k] * matrix_b[k, col] for k in range(cols)) for col in range(cols)]
def multiply_matrices(matrix_size, parallel=False, num_threads=None):
matrix_a = np.random.randint(1, 10, size=(matrix_size, matrix_size)) # Генерация целых чисел от 1 до 10
matrix_b = np.random.randint(1, 10, size=(matrix_size, matrix_size))
if parallel:
start_time = time.time()
args = [(row, matrix_a, matrix_b, matrix_size) for row in range(matrix_size)]
with Pool(num_threads) as pool:
result = np.array(pool.map(multiply_matrices_parallel, args))
end_time = time.time()
else:
start_time = time.time()
result = multiply_matrices_sequential(matrix_a, matrix_b)
end_time = time.time()
execution_time = end_time - start_time
return matrix_a, matrix_b, result, execution_time
def run_multiplication():
matrix_size = int(matrix_size_entry.get())
algorithm_choice = algorithm_var.get()
parallel = True if algorithm_choice == 'Параелльный' else False
num_threads = int(threads_entry.get()) if parallel else None
matrix_a, matrix_b, result, execution_time = multiply_matrices(matrix_size, parallel, num_threads)
result_text.config(state=tk.NORMAL)
result_text.delete("1.0", tk.END)
result_text.insert(tk.END, f"Результат:\n{result}\n\nВремя: {execution_time:.6f} секунд")
result_text.config(state=tk.DISABLED)
matrix_a_text.config(state=tk.NORMAL)
matrix_a_text.delete("1.0", tk.END)
matrix_a_text.insert(tk.END, f"Матрица A:\n{matrix_a}")
matrix_a_text.config(state=tk.DISABLED)
matrix_b_text.config(state=tk.NORMAL)
matrix_b_text.delete("1.0", tk.END)
matrix_b_text.insert(tk.END, f"Матрица B:\n{matrix_b}")
matrix_b_text.config(state=tk.DISABLED)
# GUI setup
root = tk.Tk()
root.title("Matrix Multiplication")
# Matrix Size
matrix_size_label = ttk.Label(root, text="Размер матрицы:")
matrix_size_label.grid(row=0, column=0, padx=5, pady=5)
matrix_size_entry = ttk.Entry(root)
matrix_size_entry.grid(row=0, column=1, padx=5, pady=5)
matrix_size_entry.insert(0, "")
# Algorithm Choice
algorithm_label = ttk.Label(root, text="Алгоритм:")
algorithm_label.grid(row=1, column=0, padx=5, pady=5)
algorithm_var = tk.StringVar(value="Обычный")
algorithm_combobox = ttk.Combobox(root, textvariable=algorithm_var, values=["Обычный", "Паралелльный"])
algorithm_combobox.grid(row=1, column=1, padx=5, pady=5)
# Threads (only for parallel algorithm)
threads_label = ttk.Label(root, text="Потоки:")
threads_label.grid(row=2, column=0, padx=5, pady=5)
threads_entry = ttk.Entry(root)
threads_entry.grid(row=2, column=1, padx=5, pady=5)
threads_entry.insert(0, "4")
#threads_entry.state(['readonly']) # make it read-only initially
# Run Button
run_button = ttk.Button(root, text="Начать", command=run_multiplication)
run_button.grid(row=3, column=0, columnspan=2, pady=10)
# Result Text
result_text = tk.Text(root, height=15, width=50, state=tk.DISABLED)
result_text.grid(row=4, column=0, columnspan=2, padx=10, pady=10)
# Generated Matrix A
matrix_a_text = tk.Text(root, height=10, width=25, state=tk.DISABLED)
matrix_a_text.grid(row=5, column=0, padx=10, pady=5)
# Generated Matrix B
matrix_b_text = tk.Text(root, height=10, width=25, state=tk.DISABLED)
matrix_b_text.grid(row=5, column=1, padx=10, pady=5)
root.mainloop()