4 Commits

Author SHA1 Message Date
a0adf05443 Commit переделанный финальный 2023-12-21 17:06:33 +04:00
fc694e32d5 commit 2023-12-21 00:41:47 +04:00
57ba19a35a commit переделанный 2023-12-21 00:36:09 +04:00
3fdbc64151 commit1 2023-12-18 16:35:00 +04:00
44 changed files with 599 additions and 335 deletions

View File

@@ -1,7 +1,10 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# User-specific files
*.rsuser
@@ -399,6 +402,7 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
@@ -475,3 +479,6 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

View File

@@ -0,0 +1,80 @@
# Отчет по лабораторной работе №3
Выполнил студент гр. ИСЭбд-41 Дунаев О.И.
## REST API, Gateway и синхронный обмен между микросервисами
## Создание микросервисов
1. С помощью команды `dotnet new web -n worker-2` в терминале создал первый микросервис.
2. Добавил решение командой `dotnet new sln`
3. Связал решение и проект командой `dotnet sln worker-2.sln add worker-2.csproj`
4. Повторил действие для второго микросервиса
5. Добавил библиотеку Swagger и OpenAi в проекты и запустил с помощью команды `dotnet run`
Скриншоты протестированных микросервисов:
![](pic/1.png)
![](pic/2.png)
![](pic/4.png)
## Реализация синхронного обмена
Реализовал код, который вызывает сихронно данные из соседнего микросервиса.
```cs
//worker-2
app.MapGet("/Locations/", async () =>
{
var httpClient = new HttpClient();
var secondWorkerResponse = await httpClient.GetStringAsync("http://worker-1:8080/");
return secondWorkerResponse.ToArray();
})
.WithName("GetBreeds")
.WithOpenApi();
## Реализация gateway при помощи nginx
Добавил nginx.conf:
```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:
![](pic/3.png)
![](pic/5.png)

View File

@@ -0,0 +1,15 @@
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

@@ -0,0 +1,26 @@
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.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,13 @@
<!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

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

View File

@@ -0,0 +1,112 @@
List<Pets> pets = new()
{
new Pets() { Uuid= Guid.Parse("6a1b4a72-5669-41fe-8d5b-106dc86f58bd"), Animals = "Кот", Breed = "Бигль"},
new Pets() { Uuid= Guid.Parse("464bbdb8-39c0-4644-b9c0-3df1c484ea7e"), Animals = "Собака", Breed = "Мейн-Кун"},
new Pets() { Uuid= Guid.Parse("f8692bea-b7e6-4164-b564-a921f16c35c9"), Animals = "Хомяк", Breed = "Лемминг"},
};
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 pets.Select(r => new PetEntityDto()
{
Uuid = r.Uuid,
Animals = r.Animals,
Breed = r.Breed,
});
})
.WithName("GetPets")
.WithOpenApi();
app.MapGet("/{uuid}", (Guid uuid) =>
{
var pet = pets.FirstOrDefault(r => r.Uuid == uuid);
if (pet == null)
return Results.NotFound();
return Results.Json(new PetEntityDto()
{
Uuid = pet.Uuid,
Animals = pet.Animals,
Breed = pet.Breed,
});
})
.WithName("GetPetByGUID")
.WithOpenApi();
app.MapPost("/{animals}/{breed}", (string Animals, string Breed) =>
{
Guid NewGuid = Guid.NewGuid();
pets.Add(new Pets() { Uuid = NewGuid, Animals = (string)Animals, Breed = (string)Breed});
var pet = pets.FirstOrDefault(r => r.Uuid == NewGuid);
if (pet == null)
return Results.NotFound();
return Results.Json(new PetEntityDto()
{
Uuid = pet.Uuid,
Animals = pet.Animals,
Breed = pet.Breed,
});
})
.WithName("PostPet")
.WithOpenApi();
app.MapPatch("/{uuid}/{animals}/{breed}", (Guid uuid, string ?animals, string ?breed) =>
{
var pet = pets.FirstOrDefault(r => r.Uuid == uuid);
if (pet == null)
return Results.NotFound();
if (animals != null) pet.Animals = animals;
if (breed != null) pet.Breed = breed;
return Results.Json(new PetEntityDto()
{
Uuid = pet.Uuid,
Animals = pet.Animals,
Breed = pet.Breed,
});
})
.WithName("UpdatePet")
.WithOpenApi();
app.MapDelete("/{uuid}", (Guid uuid) =>
{
var pet = pets.FirstOrDefault(r => r.Uuid == uuid);
if (pet == null)
return Results.NotFound();
pets.Remove(pet);
return Results.Json(new PetEntityDto()
{
Uuid = pet.Uuid,
Animals = pet.Animals,
Breed = pet.Breed,
});
})
.WithName("DeletePetByGUID")
.WithOpenApi();
app.Run();
public class Pets
{
public Guid Uuid { get; set; }
public string Animals { get; set; } = string.Empty;
public string Breed { get; set; } = string.Empty;
}
public class PetEntityDto : Pets { }

View File

@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51956",
"sslPort": 44303
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5197",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7027;http://localhost:5197",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>worker_1</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
</Project>

View File

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

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", "{90F6C7BD-78E2-47C8-A702-DD47E74D3865}"
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
{90F6C7BD-78E2-47C8-A702-DD47E74D3865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90F6C7BD-78E2-47C8-A702-DD47E74D3865}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90F6C7BD-78E2-47C8-A702-DD47E74D3865}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90F6C7BD-78E2-47C8-A702-DD47E74D3865}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

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

View File

@@ -0,0 +1,139 @@
List<Location> locations = new()
{
new Location() { Uuid= Guid.NewGuid(), Habitat = "Америка", IsSingleLocation = true, IdBreed = Guid.Parse("6a1b4a72-5669-41fe-8d5b-106dc86f58bd") },
new Location() { Uuid= Guid.NewGuid(), Habitat = "Россия", IsSingleLocation = false, IdBreed = Guid.Parse("f8692bea-b7e6-4164-b564-a921f16c35c9") },
new Location() { Uuid= Guid.NewGuid(), Habitat = "Китай", IsSingleLocation = false, IdBreed = Guid.Parse("464bbdb8-39c0-4644-b9c0-3df1c484ea7e") },
new Location() { Uuid= Guid.NewGuid(), Habitat = "Хорватия", IsSingleLocation = true, IdBreed = 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 locations.Select(r => new LocationEntityDto()
{
Uuid = r.Uuid,
Habitat = r.Habitat,
IsSingleLocation = r.IsSingleLocation,
IdBreed = r.IdBreed,
});
})
.WithName("GetLocations")
.WithOpenApi();
app.MapGet("/{uuid}", (Guid uuid) =>
{
var location = locations.FirstOrDefault(r => r.Uuid == uuid);
if (location == null)
return Results.NotFound();
return Results.Json(new LocationEntityDto()
{
Uuid = location.Uuid,
Habitat = location.Habitat,
IsSingleLocation = location.IsSingleLocation,
IdBreed = location.IdBreed,
});
})
.WithName("GetLocationByGUID")
.WithOpenApi();
app.MapPost("/{habitat}/{isSingleLocation}/{idBreed}", (string? Habitat, bool IsSingleLocation, Guid IdBreed) =>
{
Guid NewGuid = Guid.NewGuid();
locations.Add(new Location() { Uuid = NewGuid, Habitat = (string)Habitat, IsSingleLocation = (bool)IsSingleLocation, IdBreed = (Guid)IdBreed });
var location = locations.FirstOrDefault(r => r.Uuid == NewGuid);
if (location == null)
return Results.NotFound();
return Results.Json(new LocationEntityDto()
{
Uuid = location.Uuid,
Habitat = location.Habitat,
IsSingleLocation = location.IsSingleLocation,
IdBreed = location.IdBreed,
});
})
.WithName("PostLocation")
.WithOpenApi();
app.MapPatch("/{uuid}/{habitat}/{isSingleLocation}/{idBreed}", (Guid uuid, string ?habitat, bool isSingleLocation, Guid idBreed) =>
{
var location = locations.FirstOrDefault(r => r.Uuid == uuid);
if (location == null)
return Results.NotFound();
if (habitat != ",") location.Habitat = habitat;
if (isSingleLocation != location.IsSingleLocation) location.IsSingleLocation = isSingleLocation;
if (idBreed != location.IdBreed) location.IdBreed = idBreed;
return Results.Json(new LocationEntityDto()
{
Uuid = location.Uuid,
Habitat = location.Habitat,
IsSingleLocation = location.IsSingleLocation,
IdBreed = location.IdBreed,
});
})
.WithName("UpdateLocation")
.WithOpenApi();
app.MapDelete("/{uuid}", (Guid uuid) =>
{
var location = locations.FirstOrDefault(r => r.Uuid == uuid);
if (location == null)
return Results.NotFound();
locations.Remove(location);
return Results.Json(new LocationEntityDto()
{
Uuid = location.Uuid,
Habitat = location.Habitat,
IsSingleLocation = location.IsSingleLocation,
IdBreed = location.IdBreed,
});
})
.WithName("DeleteLocation")
.WithOpenApi();
app.MapGet("/Locations/", async () =>
{
var httpClient = new HttpClient();
var secondWorkerResponse = await httpClient.GetStringAsync("http://worker-1:8080/");
return secondWorkerResponse.ToArray();
})
.WithName("GetBreeds")
.WithOpenApi();
app.Run();
public class Location
{
public Guid Uuid { get; set; }
public string Habitat { get; set; } = string.Empty;
public bool IsSingleLocation { get; set; }
public Guid IdBreed { get; set; }
}
public class LocationEntityDto : Location { }
public class Breeds
{
public Guid Uuid { get; set; }
public string Animals { get; set; } = string.Empty;
public string Breed { get; set; } = string.Empty;
}
public class BreedEntityDto : Breeds { }

View File

@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:36404",
"sslPort": 44384
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5101",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7125;http://localhost:5101",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>worker_2</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
</Project>

View File

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

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", "{C9D63524-2C63-4E86-91B6-D86955CFA5F8}"
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
{C9D63524-2C63-4E86-91B6-D86955CFA5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9D63524-2C63-4E86-91B6-D86955CFA5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9D63524-2C63-4E86-91B6-D86955CFA5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9D63524-2C63-4E86-91B6-D86955CFA5F8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -1,78 +0,0 @@
## Создание приложений
Создадим 2 приложения.
Был выбран язык C# и технология .NET 5.
Для создания обычных консольных приложений воспользуемся командами:
```sh
dotnet new console -o worker-1
dotnet new console -o worker-2
```
Согласно варианту, программа 1 ищет в каталоге /var/data файл с наибольшим количеством строк и перекладывает его в /var/result/data.txt.
[Исходный код программы worker-1](worker-1/Program.cs)
Согласно варианту программа 2 должна искать набольшее число из файла /var/data/data.txt и сохраняет его вторую степень в /var/result/result.txt.
[Исходный код программы worker-2](worker-2/Program.cs)
Дополнительно создан файл [.gitignore](.gitignore) для того, чтобы не закоммитить в git ничего лишнего.
## Настройка окружения
Для связи двух приложений воспользуемся следующей схемой:
1. Каталог `./data` должен быть примонтирован в каталог `/var/data` для программы 1.
Оттуда будут браться исходные данные.
2. Каталог `./result-1` должен быть примонтирован в каталог `/var/result` для программы 2.
Туда будут складываться промежуточные данные.
3. Каталог `./result-1` также должен быть примонтирован в каталог `/var/data` для программы 2.
Оттуда будут браться промежуточные результаты.
4. Каталог `./result` должен быть примонтирован в каталог `/var/result` для программы 2.
Туда будут складывать результаты финальной обработки.
Для каждой программы были созданы файлы Dockerfile ([программа 1](worker-1/Dockerfile), [программа 2](worker-2/Dockerfile)) с подробным описанием процесса сборки.
Был создан файл [docker-compose.yml](docker-compose.yml), в котором указан манифест для запуска распределённого приложения.
## Сборка и запуск
1. В каталог `./data` помещены 3 файла с различными названиями и содержимым.
![](scrins/1.png)
На выходе программа должна записать данные из рандомного файла директории `/var/data`.
![](scrins/5.png)
![](scrins/3.png)
![](scrins/4.png)
2. Теперь, обрабатывая эти файлы:
![](scrins/2.png)
На выходе программа должна записать число 7921 в `./result` так как в файле c названием data.txt наибольшее число = 89.
![](scrins/6.png)
Для запуска приложения необходимо ввести команду `docker compose up --build`.
Результат запуска после сборки:
```
[+] Running 2/1
✔ Container lab_2-worker-1-1 Created 0.0s
✔ Container lab_2-worker-2-1 Created 0.0s
Attaching to lab_2-worker-1-1, lab_2-worker-2-1
lab_2-worker-1-1 | Файл /var/data/data.txt успешно скопирован в /var/result/data.txt.
lab_2-worker-1-1 exited with code 0
lab_2-worker-2-1 | Квадрат наибольшего числа сохранено в файле: /var/result/result.txt
lab_2-worker-2-1 exited with code 0
```
В результате в каталоге `./result` создался файл `result.txt` с содержимым `7921`, что соответствует входным данным.
Изменение значений в файлах из каталога `./data` также изменяет содержимое в файлах из каталогов `./result-1` и `./result`.

View File

@@ -1,6 +0,0 @@
12
32
43
23
65
43

View File

@@ -1,3 +0,0 @@
12
1
2

View File

@@ -1,10 +0,0 @@
54
65
3
24
67
89
32
1
5
74

View File

@@ -1,18 +0,0 @@
version: "3.1"
services:
worker-1:
build: ./worker-1
volumes:
# Монтирует локальную папку data к папке data в контейнере.
- ./data:/var/data
# Монтирует локальную папку result-1 к папке result в контейнере.
- ./result-1:/var/result
worker-2:
build: ./worker-2
volumes:
# Монтирует локальную папку result-1 к папке data в контейнере.
- ./result-1:/var/data
- ./result:/var/result
# Зависимость от первого приложения.
depends_on:
- worker-1

View File

@@ -1,28 +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\worker-1.csproj", "{80526535-7D67-463B-BCDF-F1597E28E1E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-2", "worker-2\worker-2.csproj", "{5F199E11-291F-4AB7-9422-A24FD4EA5727}"
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
{80526535-7D67-463B-BCDF-F1597E28E1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80526535-7D67-463B-BCDF-F1597E28E1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80526535-7D67-463B-BCDF-F1597E28E1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80526535-7D67-463B-BCDF-F1597E28E1E4}.Release|Any CPU.Build.0 = Release|Any CPU
{5F199E11-291F-4AB7-9422-A24FD4EA5727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F199E11-291F-4AB7-9422-A24FD4EA5727}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F199E11-291F-4AB7-9422-A24FD4EA5727}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F199E11-291F-4AB7-9422-A24FD4EA5727}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -1,10 +0,0 @@
54
65
3
24
67
89
32
1
5
74

View File

@@ -1 +0,0 @@
7921

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,18 +0,0 @@
# Задаем базовый образ на .net
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
# Задаем рабочую директорию
WORKDIR /src
# Копируем файлы и папки в каталог в контейнер
COPY . ./
# Создаем образы и устанавливаем данные пакеты в контейнер
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /publish
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /publish
COPY --from=build-env /publish .
# Вызываем приложение во время выполнения контейнера
ENTRYPOINT ["dotnet", "worker-1.dll"]

View File

@@ -1,60 +0,0 @@
using System;
using System.IO;
namespace FileManipulation
{
class Program
{
static void Main(string[] args)
{
string sourceDirectoryPath = "/var/data";
string destinationFilePath = "/var/result/data.txt";
string fileWithMostLines = string.Empty;
int maxLineCount = 0;
try
{
DirectoryInfo sourceDirectory = new DirectoryInfo(sourceDirectoryPath);
FileInfo[] files = sourceDirectory.GetFiles();
foreach (var file in files)
{
int lineCount = File.ReadLines(file.FullName).Count();
if (lineCount > maxLineCount)
{
maxLineCount = lineCount;
fileWithMostLines = file.FullName;
}
}
if (!string.IsNullOrEmpty(fileWithMostLines))
{
// Перемещение файла с наибольшим количеством строк в новое место
File.Move(fileWithMostLines, destinationFilePath);
Console.WriteLine($"Файл {fileWithMostLines} успешно перемещен в {destinationFilePath}.");
}
else
{
Console.WriteLine("В указанном каталоге нет файлов.");
}
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("Указанный каталог не существует.");
}
catch (IOException ex)
{
Console.WriteLine($"Произошла ошибка при перемещении файла: {ex.Message}");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Недостаточно прав для доступа к каталогу или файлу.");
}
catch (Exception ex)
{
Console.WriteLine($"Произошла непредвиденная ошибка: {ex.Message}");
}
}
}
}

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>worker_1</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
</Project>

View File

@@ -1,18 +0,0 @@
# Задаем базовый образ на .net
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
# Задаем рабочую директорию
WORKDIR /src
# Копируем файлы и папки в каталог в контейнер
COPY . ./
# Создаем образы и устанавливаем данные пакеты в контейнер
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /publish
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /publish
COPY --from=build-env /publish .
# Вызываем приложение во время выполнения контейнера
ENTRYPOINT ["dotnet", "worker-2.dll"]

View File

@@ -1,60 +0,0 @@
using System;
using System.IO;
namespace FileManipulation
{
class Program
{
static void Main(string[] args)
{
string sourceDirectoryPath = "/var/data";
string destinationFilePath = "/var/result/data.txt";
string fileWithMostLines = string.Empty;
int maxLineCount = 0;
try
{
DirectoryInfo sourceDirectory = new DirectoryInfo(sourceDirectoryPath);
FileInfo[] files = sourceDirectory.GetFiles();
foreach (var file in files)
{
int lineCount = File.ReadLines(file.FullName).Count();
if (lineCount > maxLineCount)
{
maxLineCount = lineCount;
fileWithMostLines = file.FullName;
}
}
if (!string.IsNullOrEmpty(fileWithMostLines))
{
// Перемещение файла с наибольшим количеством строк в новое место
File.Move(fileWithMostLines, destinationFilePath);
Console.WriteLine($"Файл {fileWithMostLines} успешно перемещен в {destinationFilePath}.");
}
else
{
Console.WriteLine("В указанном каталоге нет файлов.");
}
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("Указанный каталог не существует.");
}
catch (IOException ex)
{
Console.WriteLine($"Произошла ошибка при перемещении файла: {ex.Message}");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Недостаточно прав для доступа к каталогу или файлу.");
}
catch (Exception ex)
{
Console.WriteLine($"Произошла непредвиденная ошибка: {ex.Message}");
}
}
}
}

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>worker_2</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
</Project>