1 Commits

Author SHA1 Message Date
b9af3a3cb2 commit1 2023-12-18 18:10:32 +04:00
350 changed files with 754 additions and 10234 deletions

View File

@@ -7,8 +7,8 @@
1. [Знакомство с docker и docker-compose](labs/lab_1/README.md)
2. [Разработка простейшего распределённого приложения](labs/lab_2/README.md)
3. [REST API, Gateway и синхронный обмен между микросервисами](labs/lab_3/README.md)
4. [Работа с брокером сообщений](labs/lab_4/README.md)
3. TBA
4. TBA
5. TBA
6. TBA
7. TBA

View File

@@ -1,129 +0,0 @@
# Лабораторная работа №3 - REST API, Gateway и синхронный обмен между микросервисами
Цель: изучение шаблона проектирования gateway, построения синхронного обмена между микросервисами и архитектурного стиля RESTful API.
Задачи:
1. Создать 2 микросервиса, реализующих CRUD на связанных сущностях.
2. Реализовать механизм синхронного обмена сообщениями между микросервисами.
3. Реализовать шлюз на основе прозрачного прокси-сервера nginx.
## Создание микросервисов
Создать два микросервиса.
Каждый сервис реализует CRUD-операции: список записей, подробности конкретной записи, создание, удаление и изменение записи.
В качестве хранилища данных может выступать оперативная память приложения или база данных.
Сущности необходимо подобрать по следующим критериям:
1. Они должны быть связаны с предполагаемой темой диплома.
2. Они должны быть связаны как `1-ко-многим``.
> Например, одна сущность - книга в библиотеке, вторая - абонемент.
>
> Поля абонемента: УИД (уникальный идентификатор) абонемента, Номер, ФИО читателя, Дата выдачи.
> Поля книги: УИД книги, Автор, Название, Год издания, УИД абонемента, на котором сейчас находится книга.
Общение между сервисами должно происходить при помощи API, реализованного при помощи архитектурного стиля проектирования REST.
То есть необходимо реализовать следующие endpoints:
1. "GET /" - Получение списка записей.
Должен возвращать массив моделей.
2. "GET /{uuid}" - Получение подробностей записи по УИД (uuid).
Должен возвращать модель или ошибку 404.
3. "POST /" - Создание новой записи.
Принимает на вход данные. Должен возвращать модель из п.2.
4. "PUT /{uuid}" - Обновление записи по УИД.
Принимает на вход новые данные. Должен возвращать модель из п.2 или ошибку 404.
5. "DELETE /{uuid}" - Удаление записи по УИД.
Возвращает коды 200 при успехе и 404, если запись не найдена.
Пример модели абонемента для списка и подробностей:
```json
{
"uuid": "8f036445-a5bd-401c-926e-840f9de795cd",
"number": 135,
"fullName": "Иванов И.И.",
"issued": "2023-10-18T05:41:00Z"
}
```
Пример модели абонемента для создания или изменения:
```json
{
"number": 135,
"fullName": "Иванов И.И.",
"issued": "2023-10-18T05:41:00Z"
}
```
> Как видите, нет УИДа, т.к. он присваивается системой, и изменять мы его не можем.
Пример модели книги для списка:
```json
{
"uuid": "8740d660-b251-4272-8535-be7ec3748d4b",
"author": "J.K.R.",
"subject": "HP and PS",
"year": 1997,
"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd"
}
```
Пример модели книги для подробностей:
```json
{
"uuid": "8740d660-b251-4272-8535-be7ec3748d4b",
"author": "J.K.R.",
"subject": "HP and PS",
"year": 1997,
"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd",
"subscriptionInfo": {
"number": 135,
"fullName": "Иванов И.И.",
"issued": "2023-10-18T05:41:00Z"
}
}
```
> Как видите, модель сильно богаче, чем при запросе списка.
>
> Как раз здесь и нужен синхронный обмен между сервисами.
Пример модели книги для создания или изменения:
```json
{
"author": "J.K.R.",
"subject": "HP and PS",
"year": 1997,
"subscriptionUuid": "8f036445-a5bd-401c-926e-840f9de795cd"
}
```
Как понять, куда обращаться микросервису книг для получения данных об абонементах?
Нам здесь поможет docker compose: код в "service" совпадает с хостом, куда следует обращаться.
## Реализация синхронного обмена
Как реализовать непосредственно работу с endpoints?
Например, использовать ASP.NET Core Minimal APIs.
[Небольшой пример, который это показывает](./example_1.cs).
Как вызвать синхронно данные с соседнего микросервиса?
Через HTTP-клиент!
[Небольшой пример, который это показывает](./example_2.cs).
## Реализация gateway при помощи nginx
Один сервер, несколько location, proxy_pass по хосту из docker-compose.yml, открытые порты наружу и... всё.
[Пример файла с настройкой nginx](./example_nginx.conf).
[Ещё один пример связи воркеров и nginx](../../tasks/moiseev-vv/lab_3).

View File

@@ -1,76 +0,0 @@
List<TaskEntity> tasks = new()
{
new TaskEntity() { Uuid= Guid.NewGuid(), Subject = "Сдать третью лабу", IsCompleted = false },
};
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// Массив сущностей.
app.MapGet("/", () =>
{
return tasks.Select(t => new TaskEntityDto()
{
Uuid = t.Uuid,
Subject = t.Subject,
IsCompleted = t.IsCompleted,
});
});
// Подробности сущности.
app.MapGet("/{uuid}", (Guid uuid) =>
{
var task = tasks.FirstOrDefault(t => t.Uuid == uuid);
if (task == null)
return Results.NotFound();
return Results.Json(new TaskEntityDto()
{
Uuid = task.Uuid,
Subject = task.Subject,
IsCompleted = task.IsCompleted,
});
});
// Создание сущности.
app.MapPost("/", () => { throw new NotImplementedException(); });
// Изменение сущности.
app.MapPut("/{uuid}", () => { throw new NotImplementedException(); });
// Удаление сущности.
app.MapPost("/", () => { throw new NotImplementedException(); });
app.Run();
/// <summary>
/// Сама сущность.
/// </summary>
public class TaskEntity
{
public Guid Uuid { get; set; }
public string Subject { get; set; } = string.Empty;
public bool IsCompleted { get; set; }
}
/// <summary>
/// DTO-класс для описания сущности в API.
/// </summary>
public class TaskEntityDto : TaskEntity { }
/// <summary>
/// Запрос на создание сущности.
/// </summary>
public class TaskCreateRequest
{
public string Subject { get; set; } = string.Empty;
public bool IsCompleted { get; set; }
}
/// <summary>
/// Запрос на изменение сущности.
/// </summary>
public class TaskEditRequest
{
public string Subject { get; set; } = string.Empty;
public bool IsCompleted { get; set; }
}

View File

@@ -1,26 +0,0 @@
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient(); // Добавляем библиотеку по работе с HTTP.
var app = builder.Build();
// Да, по заданию надо будет запрашивать метод /{uuid}. Тут запрашивается список.
app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
var remoteHost = "http://localhost:5158"; // Адрес, по которому развёрнут микросервис с задачами. В docker compose тут будет имя service.
var client = httpClientFactory.CreateClient();
var response = await client.GetFromJsonAsync<List<TaskEntityDto>>(remoteHost);
if (response == null)
return Results.BadRequest();
return Results.Ok($"Соседний микросервис отдал следующие задачи: {string.Join(", ", response.Select(i => i.Subject))}");
});
app.Run();
/// <summary>
/// DTO-класс для описания сущности из другого микросервиса.
/// </summary>
public class TaskEntityDto
{
public Guid Uuid { get; set; }
public string Subject { get; set; } = string.Empty;
public bool IsCompleted { get; set; }
}

View File

@@ -1,21 +0,0 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
location /test/ {
proxy_pass http://test:80/;
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 /test;
}
location /admin/ {
proxy_pass http://admin:80/;
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 /admin;
}
}

View File

@@ -1,59 +0,0 @@
# Лабораторная работа №4 - Работа с брокером сообщений
**Цель**: изучение проектирования приложений при помощи брокера сообщений.
**Задачи**:
1. Установить брокер сообщений RabbitMQ.
2. Пройти уроки 1, 2 и 3 из [RabbitMQ Tutorials](https://www.rabbitmq.com/getstarted.html) на любом языке программирования.
3. Продемонстрировать работу брокера сообщений.
## Установка брокера сообщений RabbitMQ
Можно не использовать Docker и использовать локальный ПК.
[Страница скачивания RabbitMQ с офф. сайта](https://www.rabbitmq.com/download.html).
[Страница релизов RabbitMQ](https://github.com/rabbitmq/rabbitmq-server/releases/), где есть бинарные установщики для всех современных платформ.
## Прохождение tutorial
Достаточно для каждого урока скриншота, где виден запуск одновременно `producer` и `consumer`, а также видно, что сообщения передаются.
## Разработка демонстрационных приложений
См. 3 главу tutorial.
Необходимо выбрать предметную область и разработать следующие приложения:
1. **Publisher**.
Программа, которая создаёт один **exchange** с типом _fanout_.
Программа должна раз в секунду генерировать сообщения в журнал событий согласно вашей предметной области.
Например, событие "пришёл заказ" или "сообщение от пользователя" или "необходимо создать отчёт".
2. **Consumer 1**.
Программа, которая создаёт под себя отдельную не анонимную (!) очередь (**queue**) (то есть имя queue НЕ пустая строка), создаёт **binding** на **exchange** и начинает принимать сообщения (_consume_).
Программа должна обрабатывать сообщения 2-3 секунды.
Можно реализовать через обычный _Thread.Sleep_ (для C#).
3. **Consumer 2**.
Аналогично _Consumer 1_, только сообщения необходимо обрабатывать моментально.
Только имя очереди должно отличаться от _Consumer 1_.
Далее необходимо собрать и запустить приложения одновременно по одному экземпляру.
Сделать в отчёте вывод о скорости обработки _consumer_-ами событий от _publisher_-а.
Для этого можно посмотреть заполненность созданных очередей.
А для этого можно использовать скриншот из **RabbitMQ Management UI**.
Запустить несколько копий _Consumer 1_.
Проверить заново заполненность очередей через _UI_.
## Правила оформления pull request
Код и отчёт со скриншотами необходимо положить в папку `tasks/фамилия-инициалы/lab_4`.
Не забудьте о файле `.gitignore`, чтобы не закоммитить ничего лишнего.
Для C#-проектов это, например, папки `bin` и `obj`.
Правила именования ветки: `фамилия-инициалы-lab-номер`, например, `moiseev-vv-lab-4`.
Название pull request: `[Л/Р 4] ФАМИЛИЯ ИМЯ`, например, `[Л/Р 4] Моисеев Владислав`.

View File

@@ -1,149 +0,0 @@
# Отчёт по лабораторной работе №1
Выполнил: студент гр. ИСЭбд-41, Мельников К.Ю.
## Разворачивание сервиса Gitea
Содержимое файла `docker-compose.yml` в папке Gitea:
```yaml
version: "3"
networks:
gitea:
external: false
# Контейнер Gitea
services: # Описание служб
server:
image: gitea/gitea:1.20.4 # Образ gitea
container_name: gitea # Наименование контейнера
environment: # Наши параметры
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=db:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks: # Параметры сети
- gitea
volumes: # Каталоги для хранения данных контейнера
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports: # Порт локальный и внутри сети
- "3000:3000"
- "222:22"
depends_on:
- db
# База данных
db:
image: mysql:8 # Образ БД и версия
restart: always # Параметр перезапуска
environment: # Подключаем каталог с базой данных
- MYSQL_ROOT_PASSWORD=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=gitea
- MYSQL_DATABASE=gitea
networks: # Параметры сети
- gitea
volumes: # Том для хранения данных БД
- ./mysql:/var/lib/mysql
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
![](scrins/1.png)
Открываем Docker Desktop и проверяем, что контейнер сервера БД и Gitea созданы и запущены:
![](scrins/2.png)
Переходим на http://localhost:222:
![](scrins/3.png)
Регистрируемся и автоматически входим в учетную запись:
![](scrins/4.png)
![](scrins/5.png)
## Разворачивание сервиса Wordpress
Также в файл `docker-compose.yml` в папке Wordpress прописываем следующий код:
```yaml
version: '3.1'
services:
# Контейнер Wordpress
wordpress:
image: wordpress # Образ
restart: always # Параметр перезапуска
ports: # На каком порте запускаем
- 7071:80
environment: # Настройки БД WordPress для подключения
WORDPRESS_DB_HOST: database # Имя хоста БД MySQL
WORDPRESS_DB_USER: user # Имя пользователя БД
WORDPRESS_DB_PASSWORD: password # Пароль пользователя БД
WORDPRESS_DB_NAME: name_database # Имя БД
volumes: # Каталог хранения файлов WordPress
- wordpress:/var/www/html
# Контейнер MySQL
database:
image: mysql:5.7 # Образ и его версия
restart: always # Параметр перезапуска
environment: # Настройки БД для подключения
MYSQL_DATABASE: name_database
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_RANDOM_ROOT_PASSWORD: '12345'
volumes: # Каталог хранения данных БД
- database:/var/lib/mysql
volumes:
wordpress:
database:
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
![](scrins/6.png)
Открываем Docker Desktop и проверяем, что контейнер сервера БД и Wordpress созданы и запущены
Устанавливаем Wordpress и проверяем, что все работает:
![](scrins/7.png)
![](scrins/8.png)
## Разворачивание сервиса Redmine
Также в файл `docker-compose.yml` в папке Redmine прописываем код:
```yaml
version: '3.1'
services:
# Контейнер Redmine
redmine:
image: redmine # Образ контейнера
restart: always
ports: # На какой порт запускать
- 8080:3000
environment:
REDMINE_DB_MYSQL: db
REDMINE_DB_PASSWORD: example
REDMINE_SECRET_KEY_BASE: supersecretkey
# Контейнер БД MySQL
db:
image: mysql:5.7 # Образ БД и ее версия
restart: always
environment: # Название и пароль админа БД
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: redmine
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
Открываем Docker Desktop и проверяем, что контейнер сервера БД и Redmine созданы и запущены:
![](scrins/10.png)
Переходим на http://localhost:8080:
![](scrins/9.png)
Регистрируемся и проверяем, что все работает:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -1,139 +0,0 @@
# Отчёт по лабораторной работе №1
Выполнил: студент гр. ИСЭбд-41, Дунаев О.И.
## Разворачивание сервиса Gitea
Содержимое файла `docker-compose.yml` в папке Gitea:
```yaml
version: "3"
networks:
gitea:
external: false
# Контейнер Gitea
services: # Описание служб
server:
image: gitea/gitea:1.20.4 # Образ gitea
container_name: gitea # Наименование контейнера
environment: # Наши параметры
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=db:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks: # Параметры сети
- gitea
volumes: # Каталоги для хранения данных контейнера
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports: # Порт локальный и внутри сети
- "3000:3000"
- "222:22"
depends_on:
- db
# База данных
db:
image: mysql:8 # Образ БД и версия
restart: always # Параметр перезапуска
environment: # Подключаем каталог с базой данных
- MYSQL_ROOT_PASSWORD=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=gitea
- MYSQL_DATABASE=gitea
networks: # Параметры сети
- gitea
volumes: # Том для хранения данных БД
- ./mysql:/var/lib/mysql
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
![](pic/1.png)
Переходим на http://localhost:222:
![](pic/2.png)
Регистрируемся и автоматически входим в учетную запись:
![](pic/3.png)
## Разворачивание сервиса Wordpress
Также в файл `docker-compose.yml` в папке Wordpress прописываем следующий код:
```yaml
version: '3.1'
services:
# Контейнер Wordpress
wordpress:
image: wordpress # Образ
restart: always # Параметр перезапуска
ports: # На каком порте запускаем
- 7071:80
environment: # Настройки БД WordPress для подключения
WORDPRESS_DB_HOST: database # Имя хоста БД MySQL
WORDPRESS_DB_USER: user # Имя пользователя БД
WORDPRESS_DB_PASSWORD: password # Пароль пользователя БД
WORDPRESS_DB_NAME: name_database # Имя БД
volumes: # Каталог хранения файлов WordPress
- wordpress:/var/www/html
# Контейнер MySQL
database:
image: mysql:5.7 # Образ и его версия
restart: always # Параметр перезапуска
environment: # Настройки БД для подключения
MYSQL_DATABASE: name_database
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_RANDOM_ROOT_PASSWORD: '12345'
volumes: # Каталог хранения данных БД
- database:/var/lib/mysql
volumes:
wordpress:
database:
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
![](pic/4.png)
Открываем Docker Desktop и проверяем, что контейнер сервера БД и Wordpress созданы и запущены:
![](pic/5.png)
## Разворачивание сервиса Redmine
Также в файл `docker-compose.yml` в папке Redmine прописываем код:
```yaml
version: '3.1'
services:
# Контейнер Redmine
redmine:
image: redmine # Образ контейнера
restart: always
ports: # На какой порт запускать
- 8080:3000
environment:
REDMINE_DB_MYSQL: db
REDMINE_DB_PASSWORD: example
REDMINE_SECRET_KEY_BASE: supersecretkey
# Контейнер БД MySQL
db:
image: mysql:5.7 # Образ БД и ее версия
restart: always
environment: # Название и пароль админа БД
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: redmine
```
Далее в командной строке разворачиваем сервис командой `docker-compose up -d`:
![](pic/6.png)
Переходим на http://localhost:8080:
![](pic/7.png)
Регистрируемся и проверяем, что все работает:
![](pic/8.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

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,46 @@
namespace Lab6
{
public class Alg1
{
public int Begin(int[,] matrix)
{
return CalculateDeterminant(matrix);
}
static int CalculateDeterminant(int[,] matrix)
{
int n = matrix.GetLength(0);
if (n == 1)
{
return matrix[0, 0];
}
int determinant = 0;
for (int j = 0; j < n; j++)
{
int[,] submatrix = new int[n - 1, n - 1];
for (int i = 1; i < n; i++)
{
for (int k = 0; k < n; k++)
{
if (k < j)
{
submatrix[i - 1, k] = matrix[i, k];
}
else if (k > j)
{
submatrix[i - 1, k - 1] = matrix[i, k];
}
}
}
determinant += (int)Math.Pow(-1, j) * matrix[0, j] * CalculateDeterminant(submatrix);
}
return determinant;
}
}
}

View File

@@ -0,0 +1,90 @@
using System.Diagnostics.CodeAnalysis;
using System.Drawing.Drawing2D;
namespace Lab6
{
public class Alg2
{
public double Begin(double[,] matrixA, int threadCount)
{
int size = matrixA.GetLength(0);
if (size == 1)
{
return matrixA[0, 0];
}
else if (size == 2)
{
return matrixA[0, 0] * matrixA[1, 1] - matrixA[0, 1] * matrixA[1, 0];
}
else
{
double determinant = 0;
object lockObject = new object();
Parallel.For(0, size, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, i =>
{
double[,] subMatrix = GetSubMatrix(matrixA, i);
double subDeterminant = matrixA[0, i] * Determinant(subMatrix);
lock (lockObject)
{
determinant += Math.Pow(-1, i) * subDeterminant;
}
});
return determinant;
}
}
static double[,] GetSubMatrix(double[,] matrix, int columnIndex)
{
int size = matrix.GetLength(0);
double[,] subMatrix = new double[size - 1, size - 1];
for (int i = 1; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (j < columnIndex)
{
subMatrix[i - 1, j] = matrix[i, j];
}
else if (j > columnIndex)
{
subMatrix[i - 1, j - 1] = matrix[i, j];
}
}
}
return subMatrix;
}
static double Determinant(double[,] matrix)
{
int size = matrix.GetLength(0);
if (size == 1)
{
return matrix[0, 0];
}
else if (size == 2)
{
return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0];
}
else
{
double determinant = 0;
for (int i = 0; i < size; i++)
{
double[,] subMatrix = GetSubMatrix(matrix, i);
determinant += Math.Pow(-1, i) * matrix[0, i] * Determinant(subMatrix);
}
return determinant;
}
}
}
}

View File

@@ -0,0 +1,95 @@
using System.Drawing;
namespace Lab6
{
public class Controller
{
public double[,] ConvertArray(int[,] intArray)
{
int rows = intArray.GetLength(0);
int cols = intArray.GetLength(1);
double[,] doubleArray = new double[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
doubleArray[i, j] = (double)intArray[i, j];
}
}
return doubleArray;
}
public string PrintResultMatrix(int[,] result)
{
string resultString = "";
for (int i = 0; i < result.GetLength(0); i++)
{
for (int j = 0; j < result.GetLength(1); j++)
{
resultString += result[i, j];
if (j != result.GetLength(1) - 1)
{
resultString += " ";
}
}
resultString += Environment.NewLine;
}
return resultString;
}
public int[,] GetMatrixFromTextbox(string inputText)
{
string[] lines = inputText.Split(Environment.NewLine);
int numRows = lines.Length;
int numCol = lines[0].Split(' ').Length;
int[,] matrix = new int[numRows, numCol];
for (int i = 0; i < numRows; i++)
{
string[] elements = lines[i].Split(' ');
for (int j = 0; j < numCol; j++)
{
matrix[i, j] = int.Parse(elements[j]);
}
}
return matrix;
}
public string GetTextFromFile(string filePath)
{
string text = "";
using (StreamReader sr = new StreamReader(filePath))
{
text = sr.ReadToEnd();
}
return text;
}
public int[,] GenerateNewMatrix(int count)
{
Random random = new Random();
int[,] matrix = new int[count, count];
for (int i = 0; i < count; i++)
{
for (int j = 0; j < count; j++)
{
matrix[i, j] = random.Next(1, 5);
}
}
return matrix;
}
}
}

View File

@@ -0,0 +1,222 @@
namespace Lab6
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
textBoxMatrix1 = new TextBox();
textBoxResult = new TextBox();
buttonAlg1 = new Button();
buttonAlg2 = new Button();
openFileDialog1 = new OpenFileDialog();
label3 = new Label();
labelResultTime = new Label();
label4 = new Label();
countStream = new NumericUpDown();
buttonGenerateMatrix1 = new Button();
label5 = new Label();
genCountRowCol = new NumericUpDown();
button1 = new Button();
label1 = new Label();
((System.ComponentModel.ISupportInitialize)countStream).BeginInit();
((System.ComponentModel.ISupportInitialize)genCountRowCol).BeginInit();
SuspendLayout();
//
// textBoxMatrix1
//
textBoxMatrix1.Location = new Point(58, 48);
textBoxMatrix1.Multiline = true;
textBoxMatrix1.Name = "textBoxMatrix1";
textBoxMatrix1.Size = new Size(565, 274);
textBoxMatrix1.TabIndex = 0;
//
// textBoxResult
//
textBoxResult.Location = new Point(833, 48);
textBoxResult.Multiline = true;
textBoxResult.Name = "textBoxResult";
textBoxResult.Size = new Size(258, 40);
textBoxResult.TabIndex = 1;
//
// buttonAlg1
//
buttonAlg1.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
buttonAlg1.Location = new Point(833, 186);
buttonAlg1.Name = "buttonAlg1";
buttonAlg1.Size = new Size(258, 40);
buttonAlg1.TabIndex = 2;
buttonAlg1.Text = "Обычный алгоритм";
buttonAlg1.UseVisualStyleBackColor = true;
buttonAlg1.Click += buttonAlg1_Click;
//
// buttonAlg2
//
buttonAlg2.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
buttonAlg2.Location = new Point(833, 232);
buttonAlg2.Name = "buttonAlg2";
buttonAlg2.Size = new Size(258, 39);
buttonAlg2.TabIndex = 8;
buttonAlg2.Text = "Паралелльный алгоритм";
buttonAlg2.UseVisualStyleBackColor = true;
buttonAlg2.Click += buttonAlg2_Click;
//
// openFileDialog1
//
openFileDialog1.FileName = "openFileDialog1";
//
// label3
//
label3.AutoSize = true;
label3.Font = new Font("Segoe UI", 15.75F, FontStyle.Regular, GraphicsUnit.Point);
label3.Location = new Point(23, 370);
label3.Name = "label3";
label3.Size = new Size(111, 30);
label3.TabIndex = 9;
label3.Text = "Результат:";
//
// labelResultTime
//
labelResultTime.AutoSize = true;
labelResultTime.Font = new Font("Segoe UI", 15.75F, FontStyle.Regular, GraphicsUnit.Point);
labelResultTime.Location = new Point(165, 370);
labelResultTime.Name = "labelResultTime";
labelResultTime.Size = new Size(0, 30);
labelResultTime.TabIndex = 10;
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(833, 129);
label4.Name = "label4";
label4.Size = new Size(123, 15);
label4.TabIndex = 12;
label4.Text = "Количество потоков:";
//
// countStream
//
countStream.Location = new Point(1007, 127);
countStream.Maximum = new decimal(new int[] { 10, 0, 0, 0 });
countStream.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
countStream.Name = "countStream";
countStream.Size = new Size(66, 23);
countStream.TabIndex = 13;
countStream.Value = new decimal(new int[] { 4, 0, 0, 0 });
//
// buttonGenerateMatrix1
//
buttonGenerateMatrix1.Location = new Point(268, 10);
buttonGenerateMatrix1.Name = "buttonGenerateMatrix1";
buttonGenerateMatrix1.Size = new Size(122, 32);
buttonGenerateMatrix1.TabIndex = 14;
buttonGenerateMatrix1.Text = "Сгенерировать";
buttonGenerateMatrix1.UseVisualStyleBackColor = true;
buttonGenerateMatrix1.Click += buttonGenerateMatrix1_Click;
//
// label5
//
label5.AutoSize = true;
label5.Location = new Point(833, 100);
label5.Name = "label5";
label5.Size = new Size(166, 15);
label5.TabIndex = 16;
label5.Text = "Размерность при генерации:";
//
// genCountRowCol
//
genCountRowCol.Location = new Point(1007, 98);
genCountRowCol.Maximum = new decimal(new int[] { 500, 0, 0, 0 });
genCountRowCol.Minimum = new decimal(new int[] { 2, 0, 0, 0 });
genCountRowCol.Name = "genCountRowCol";
genCountRowCol.Size = new Size(66, 23);
genCountRowCol.TabIndex = 17;
genCountRowCol.Value = new decimal(new int[] { 3, 0, 0, 0 });
//
// button1
//
button1.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
button1.Location = new Point(833, 295);
button1.Name = "button1";
button1.Size = new Size(258, 46);
button1.TabIndex = 22;
button1.Text = "Очистить матрицы";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Segoe UI", 15.75F, FontStyle.Regular, GraphicsUnit.Point);
label1.Location = new Point(833, 12);
label1.Name = "label1";
label1.Size = new Size(240, 30);
label1.TabIndex = 23;
label1.Text = "Детерминант матрицы:";
//
// Form1
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1132, 534);
Controls.Add(label1);
Controls.Add(button1);
Controls.Add(genCountRowCol);
Controls.Add(label5);
Controls.Add(buttonGenerateMatrix1);
Controls.Add(countStream);
Controls.Add(label4);
Controls.Add(labelResultTime);
Controls.Add(label3);
Controls.Add(buttonAlg2);
Controls.Add(buttonAlg1);
Controls.Add(textBoxResult);
Controls.Add(textBoxMatrix1);
Name = "Form1";
Text = "Перемножение матриц: Дунаев О.И. ИСЭбд-41";
((System.ComponentModel.ISupportInitialize)countStream).EndInit();
((System.ComponentModel.ISupportInitialize)genCountRowCol).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBoxMatrix1;
private TextBox textBoxResult;
private Button buttonAlg1;
private Button buttonAlg2;
private OpenFileDialog openFileDialog1;
private Label label3;
private Label labelResultTime;
private Label label4;
private NumericUpDown countStream;
private Button buttonGenerateMatrix1;
private Label label5;
private NumericUpDown genCountRowCol;
private Button button1;
private Label label1;
}
}

View File

@@ -0,0 +1,90 @@
using System.Diagnostics;
namespace Lab6
{
public partial class Form1 : Form
{
public Controller service;
public Alg1 Alg1;
public Alg2 Alg2;
public Stopwatch stopwatch;
public int[,] matrixA;
public Form1()
{
InitializeComponent();
this.service = new Controller();
this.Alg1 = new Alg1();
this.Alg2 = new Alg2();
this.stopwatch = new Stopwatch();
}
private void buttonAlg1_Click(object sender, EventArgs e)
{
try
{
stopwatch.Start();
int result = Alg1.Begin(matrixA);
stopwatch.Stop();
labelResultTime.Text = "" + stopwatch.Elapsed;
textBoxResult.Text = Convert.ToString(result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
stopwatch.Reset();
}
private void buttonAlg2_Click(object sender, EventArgs e)
{
try
{
double[,] doubleMatrix = service.ConvertArray(matrixA);
stopwatch.Start();
textBoxResult.Text = Convert.ToString(Alg2.Begin(doubleMatrix, (int)countStream.Value));
stopwatch.Stop();
labelResultTime.Text = "" + stopwatch.Elapsed;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
stopwatch.Reset();
}
private void buttonLoadMatrix1_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
string filePath = openFileDialog1.FileName;
string result = service.GetTextFromFile(filePath);
textBoxMatrix1.Text = result;
matrixA = service.GetMatrixFromTextbox(result);
}
private void buttonGenerateMatrix1_Click(object sender, EventArgs e)
{
matrixA = service.GenerateNewMatrix((int)genCountRowCol.Value);
textBoxMatrix1.Text = service.PrintResultMatrix(matrixA);
}
private void button1_Click(object sender, EventArgs e)
{
textBoxMatrix1.Text = "";
textBoxResult.Text = "";
matrixA = null;
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing"">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>7, 19</value>
</metadata>
</root>

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

View File

@@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33723.286
VisualStudioVersion = 17.3.32811.315
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker_1_var_4", "worker_1_var_4.csproj", "{FC249DB1-3674-40D3-9747-7C97BAFD9172}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lab6", "Lab6.csproj", "{5E467820-7298-4466-AD82-CEDEB780CA68}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FC249DB1-3674-40D3-9747-7C97BAFD9172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC249DB1-3674-40D3-9747-7C97BAFD9172}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC249DB1-3674-40D3-9747-7C97BAFD9172}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC249DB1-3674-40D3-9747-7C97BAFD9172}.Release|Any CPU.Build.0 = Release|Any CPU
{5E467820-7298-4466-AD82-CEDEB780CA68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E467820-7298-4466-AD82-CEDEB780CA68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E467820-7298-4466-AD82-CEDEB780CA68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E467820-7298-4466-AD82-CEDEB780CA68}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {510889DE-4297-48C0-A313-416833248538}
SolutionGuid = {7933D480-E7B1-4658-8726-83CCD3BED00D}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,17 @@
namespace Lab6
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}

View File

@@ -0,0 +1,42 @@
# Отчет по лабораторной работе №6
Выполнил студент гр. ИСЭбд-41 Дунаев О.И.
## Создание приложения
Выбрал язык C#, Windows Forms.
Приложение имеет поле ввода матрицы, в которое можно через пробел вносить элементы матрицы. При необходимости можно сгенерировать матрицу указав её размерность . При необходимости можно очистить матрицу и определитель. Количество потоков в параллельном алгоритме регулируется в соответствующем поле.
Попробуем запустить обычный и паралелльный алгоритмы на матрицах 3х3 и зафиксировать результат выполнения по времени.
![](pic/1.png)
![](pic/2.png)
## Бенчмарки
Протестируем обычный и параллельный алгоритм определение детерминанта на различной размерности матрицы.
В ходе экспериментов было установлено, что обработка матрицы размеров больше 12х12 занимает слишком много времени в обычном алгоритме, поэтому для тестирования возьмем матрицы 5х5, 8х8 и 11х11.
Сверху отображен результат обычного алгоритма, снизу паралелльного.
Матрица 5х5
![](pic/5x5№1.png)
![](pic/5x5№2.png)
Матрицы 8x8
![](pic/8x8№1.png)
![](pic/8x8№2.png)
Матрицы 12х12
![](pic/12x12№1.png)
![](pic/12x12№2.png)
Вывод: Параллельный алгоритм работает быстрее только при наличии большого количества операций. Если операций не так много, то обычный алгоритм справляется быстрее.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1,2 +0,0 @@
*/*/bin
*/*/obj

View File

@@ -1,477 +0,0 @@
## 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
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk

View File

@@ -1,77 +0,0 @@
# Отчёт по лабораторной работе №2
Выполнил: студент гр. ИСЭбд-41 Фомичев Андрей.
Вариант программы 1: Ищет в каталоге `/var/data` файл с самым коротким названием и перекладывает его в `/var/result/data.txt`.
Вариант программы 2: Ищет наименьшее число из файла `/var/data/data.txt` и сохраняет количество таких чисел из последовательности в `/var/result/result.txt`.
## Создание приложений
Создадим 2 приложения.
Был выбран язык C# и технология .NET 7.
Для создания обычных консольных приложений воспользуемся командами:
```sh
dotnet new console -o worker-1
dotnet new console -o worker-2
```
Согласно варианту, программа 1 должна брать все файлы из папки `/var/data`, считывать длину их названия, найти минимальное и переложить его в папку `/var/result`.
[Исходный текст программы worker-1](worker-1/Program.cs)
Согласно варианту программа 2 должна брать строки из папки `/var/data/` с скопированным файлом, пытаться привести их к числам, затем найти минимальное из них.
Далее найти количество вхождений этого числа и результат записать в файл `/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), в котором указан манифест для запуска распределённого приложения.
Дополнительно был создан файл [.dockerignore](.dockerignore) и дополнен [.gitignore](.gitignore), чтобы исключить для сборки и коммита всё лишнее.
## Сборка и запуск
В каталог `./data` помещены 4 файла с различной длиной названия и содержимым.
![](image2.PNG)
На выходе, программа должна записать число 2, так как файл с минимальным названием f.txt, в нём минимальное число -100, которое встречается 2 раза.
![](image1.PNG)
Для запуска приложения необходимо ввести команду `docker compose up --build`.
Результат запуска после сборки:
```
[+] Running 2/2
✔ Container lab_2-worker-1-1 Created 0.0s
✔ Container lab_2-worker-2-1 Recreated 0.1s
Attaching to lab_2-worker-1-1, lab_2-worker-2-1
lab_2-worker-1-1 | Сервис 1 отработал успешно!
lab_2-worker-1-1 exited with code 0
lab_2-worker-2-1 | Сервис 2 отработал успешно!
lab_2-worker-2-1 | Наименьшее число:= -100 , число вхождений:= 2
lab_2-worker-2-1 exited with code 0
```
В результате в каталоге `./result` создался файл `result.txt` с содержимым `2`, что соответствует входным данным.
Изменение значений в файлах из каталога `./data` также изменяет содержимое в файлах из каталогов `./result-1` и `./result`.

View File

@@ -1,29 +0,0 @@
2
5
3456
468
24
3
67846
84
62
4
7468
23
34
67458446
7
-100
735
35
7
24
6458
745689
3
3457
-100
72346

View File

@@ -1,3 +0,0 @@
test
test123
test567

View File

@@ -1,19 +0,0 @@
{ "menu":
{
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{
"value": "New", "onclick": "CreateNewDoc()"
},
{
"value": "Open", "onclick": "OpenDoc()"
},
{
"value": "Close", "onclick": "CloseDoc()"
}
]
}
}
}

View File

@@ -1,5 +0,0 @@
5
6
7
8
9

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

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", "{A8D5EB71-2620-40E5-9AC5-3292588391DA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-2", "worker-2\worker-2.csproj", "{D1CDD34F-8407-4BA9-B81C-22B92532D339}"
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
{A8D5EB71-2620-40E5-9AC5-3292588391DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8D5EB71-2620-40E5-9AC5-3292588391DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8D5EB71-2620-40E5-9AC5-3292588391DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8D5EB71-2620-40E5-9AC5-3292588391DA}.Release|Any CPU.Build.0 = Release|Any CPU
{D1CDD34F-8407-4BA9-B81C-22B92532D339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1CDD34F-8407-4BA9-B81C-22B92532D339}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1CDD34F-8407-4BA9-B81C-22B92532D339}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1CDD34F-8407-4BA9-B81C-22B92532D339}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

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

View File

@@ -1,29 +0,0 @@
var dir = new DirectoryInfo("/var/data");
var files = dir.GetFiles();
string? oldFilePath = null;
var newFilePathTest = new DirectoryInfo("/var/result");
string? fileName = null;
long minFileName = long.MaxValue;
foreach(var file in files)
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file.Name);
if(fileNameWithoutExtension.Length < minFileName)
{
minFileName = fileNameWithoutExtension.Length;
oldFilePath = Path.GetFullPath(file.FullName);
fileName = file.Name;
}
}
if (oldFilePath != null)
{
foreach (var file in newFilePathTest.GetFiles())
file.Delete();
File.Copy(oldFilePath, newFilePathTest.FullName + "/" + fileName, true);
Console.WriteLine("Сервис 1 отработал успешно!");
} else
{
throw new Exception("Нет исходных файлов для чтения.");
}

View File

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

View File

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

View File

@@ -1,24 +0,0 @@
var dir = new DirectoryInfo("/var/data");
var fileName = dir.GetFiles().First().Name;
string[] numbers = File.ReadAllLines("/var/data/" + fileName);
long k = 0;
long min = long.MaxValue;
foreach (var numberStr in numbers)
{
if (!int.TryParse(numberStr, out int number))
continue;
if (number < min)
min = number;
}
foreach (var numberStr in numbers)
{
if (!int.TryParse(numberStr, out int number))
continue;
if (min == number)
k++;
}
File.WriteAllText("/var/result/result.txt", k.ToString());
Console.WriteLine("Сервис 2 отработал успешно!");
Console.WriteLine($"Наименьшее число:= {min} , число вхождений:= {k}");

View File

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

View File

@@ -1,132 +0,0 @@
# Отчёт по лабораторной работе №1
Выполнила: студентка гр. ИСЭбд-41 Горбылева Антонина Игоревна
## Разворачивание сервиса drupal
Содержимое файла `docker-compose.yml` в папке drupal:
```yaml
version: '3.1'
#Задаем контейнеры
services:
#Контейнер drupal
drupal:
image: drupal:8-apache
ports:
- 8800:80
#Каталоги в контейнере
volumes:
- /var/www/html/modules
- /var/www/html/profiles
- /var/www/html/themes
- /var/www/html/sites
restart: always
#Контейнер БД
postgres:
image: postgres:10
environment:
POSTGRES_PASSWORD: example
restart: always
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`:
Открываем Docker Desktop и проверяем, что контейнер сервера базы данных и Drupal созданы и запущены:
![](drupal_containers.png)
Переходим на http://localhost:8800, регистрируемся:
![](drupal_web.png)
Сервис запущен успешно!
## Разворачивание сервиса redmine
Содержимое файла `docker-compose.yml` в папке redmine:
```yaml
version: '3.1'
services:
# Контейнер Redmine
redmine:
image: redmine
restart: always
ports:
- 8080:3000
environment:
REDMINE_DB_MYSQL: db
REDMINE_DB_PASSWORD: example
REDMINE_SECRET_KEY_BASE: supersecretkey
# Контейнер БД
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: redmine
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`.
В Docker Desktop проверяем, что сервис работает:
![](redmine_containers.png)
Переходим на http://localhost:8800, регистрируемся:
![](redmine_web_enter.png)
Подтверждаем реистрацию и успешно заходим в свою учетную запись!
![](redmine.png)
Ура! Сервис redmine тоже работает!
## Разворачивание сервиса wordpress
Содержимое файла `docker-compose.yml` в папке wordpress:
```yaml
version: '3.1'
#Задаем контейнеры
services:
#Контейнер Wordpress
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: user
WORDPRESS_DB_PASSWORD: userpass
WORDPRESS_DB_NAME: mydb
volumes:
- wordpress:/var/www/html
#Контейнер БД
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: mydb
MYSQL_USER: user
MYSQL_PASSWORD: userpass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`.
![](docker_wordpress_terminal.png)
В Docker Desktop проверяем, что сервис запущен:
![](docker_wordpress.jpg)
Переходим на http://localhost:8080, регистрируемся и убеждаемся что сервис работает:
![](enter_wordpress.jpg)
Все три сервиса успешно запущены и работают!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

View File

@@ -1,454 +0,0 @@
## 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/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -1,84 +0,0 @@
# Отчёт по лабораторной работе №2
Выполнил: студентка гр. ИСЭбд-41, Гренадерова А.А.
Вариант программы 1: 1. Ищет в каталоге /var/data файл с наибольшим количеством строк и перекладывает его в /var/result/data.txt.
Вариант программы 2: 2. Ищет наименьшее число из файла /var/data/data.txt и сохраняет его третью степень в /var/result/result.txt.
## Создание приложений
Создадим 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 файла с различной длиной названия и содержимым.
![](2lab/1.png)
На выходе программа должна записать файл data.txt, как самый длинный по количеству строк.
![](2lab/2.png)
2. Теперь, обрабатывая этот файл:
![](2lab/2.png)
На выходе программа должна записать число 1212 в 3 степени в `./result` так как в файле c названием data.txt оно минимальное.
![](2lab/3.png)
Для запуска приложения необходимо ввести команду `docker compose up --build`.
Результат запуска после сборки:
```
[+] Running 2/0
✔ 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/result/data.txt
lab_2-worker-2-1 | The maximum number is: 8
lab_2-worker-2-1 | The count of maximum numbers is: 2
lab_2-worker-1-1 exited with code 0
lab_2-worker-2-1 exited with code 0
```
В результате в каталоге `./result` создался файл `result.txt` с содержимым `1780360128`, что соответствует входным данным.
Изменение значений в файлах из каталога `./data` также изменяет содержимое в файлах из каталогов `./result-1` и `./result`.

View File

@@ -1,3 +0,0 @@
1213
1212
12132

View File

@@ -1,2 +0,0 @@
123213
2131

View File

@@ -1 +0,0 @@
12321

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

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-1", "worker-1\worker-1.csproj", "{5B8F3FD2-C7C4-4180-80C2-3752B0648684}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "worker-2", "worker-2\worker-2.csproj", "{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|x64.ActiveCfg = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|x64.Build.0 = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|x86.ActiveCfg = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Debug|x86.Build.0 = Debug|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|Any CPU.Build.0 = Release|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|x64.ActiveCfg = Release|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|x64.Build.0 = Release|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|x86.ActiveCfg = Release|Any CPU
{5B8F3FD2-C7C4-4180-80C2-3752B0648684}.Release|x86.Build.0 = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|x64.ActiveCfg = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|x64.Build.0 = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|x86.ActiveCfg = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Debug|x86.Build.0 = Debug|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|Any CPU.Build.0 = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|x64.ActiveCfg = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|x64.Build.0 = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|x86.ActiveCfg = Release|Any CPU
{7EF62CE7-C74B-4B2F-BC91-25A367B9450E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -1,3 +0,0 @@
1213
1212
12132

View File

@@ -1 +0,0 @@
1780360128

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,42 +0,0 @@
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
string sourceDirectory = "/var/data";
string destDirectory = "/var/result";
string destFile = Path.Combine(destDirectory, "data.txt");
// Получаем все файлы в исходном каталоге
string[] files = Directory.GetFiles(sourceDirectory);
int maxLines = 0;
string filePath = "";
foreach (string file in files)
{
// Считываем строки из файла
string[] lines = File.ReadAllLines(file);
// Проверяем количество строк в файле
if (lines.Length > maxLines)
{
maxLines = lines.Length;
filePath = file;
}
}
// Копируем файл с наибольшим количеством строк в новое место
if (!string.IsNullOrEmpty(filePath))
{
File.Copy(filePath, destFile, true);
Console.WriteLine($"Файл с наибольшим количеством строк перекладывается в {destFile}");
}
else
{
Console.WriteLine("Файлы не найдены в исходном каталоге");
}
}
}

View File

@@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>worker_1</RootNamespace>
</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,38 +0,0 @@
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
string sourceFile = "/var/data/data.txt";
string resultFile = "/var/result/result.txt";
// Считываем числа из файла
string[] lines = File.ReadAllLines(sourceFile);
// Переменная для хранения наименьшего числа
int smallestNumber = int.MaxValue;
// Проходимся по всем числам в файле
foreach (string line in lines)
{
if (int.TryParse(line, out int number))
{
// Если число меньше текущего наименьшего, обновляем значение
if (number < smallestNumber)
{
smallestNumber = number;
}
}
}
// Возведение в третью степень
double result = Math.Pow(smallestNumber, 3);
// Записываем результат в файл
File.WriteAllText(resultFile, result.ToString());
Console.WriteLine("Наименьшее число из файла data.txt возведено в третью степень и сохранено в файле result.txt");
}
}

View File

@@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>worker_2</RootNamespace>
</PropertyGroup>
</Project>

View File

@@ -1,145 +0,0 @@
# Отчёт по лабораторной работе №1
Выполнил: студент гр. ИСЭбд-41 Казаков Е.В.
## Разворачивание сервиса Gitea
Содержимое файла `docker-compose.yml` в папке Gitea:
```yaml
version: "3"
networks:
gitea:
external: false
#Контейнер Gitea используется для запуска самого сервиса
services:
server:
image: gitea/gitea:1.20.4 #образ gitea
container_name: gitea
environment: #наши параметры
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=db:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes: #прописываем каталоги для хранения данных контейнера
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports: #порт локальный и внутри сети
- "3000:3000"
- "222:22"
depends_on:
- db
#Контейнер Mysql используется как сервер для запуска
db:
image: mysql:8
restart: always
environment: #подключаем каталог с базой данных
- MYSQL_ROOT_PASSWORD=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=gitea
- MYSQL_DATABASE=gitea
networks:
- gitea
volumes:
- ./mysql:/var/lib/mysql
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`:
![](shots/ss-1.png)
Открываем Docker Desktop и проверяем, что контейнер сервера базы данных и Gitea созданы и запущены:
![](shots/ss2.png)
Переходим на http://localhost:3000:
![](shots/ss3.png)
Регистрируемся и заходим на наш аккаунт
![](shots/ss4.png)
## Разворачивание сервиса Redmine
Содержимое файла `docker-compose.yml` в папке Redmine:
```yaml
version: '3.1'
#Контейнер Redmine используется для запуска самого сервиса
services:
redmine:
image: redmine #образ Redmine
restart: always
ports: #порт
- 8080:3000
environment:
REDMINE_DB_MYSQL: db
REDMINE_DB_PASSWORD: example
REDMINE_SECRET_KEY_BASE: supersecretkey
#Контейнер Mysql используется как сервер для запуска
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: redmine
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`:
![](shots/ss5.png)
Открываем Docker Desktop и проверяем, что контейнер сервера базы данных и Reamine созданы и запущены:
![](shots/ss6.png)
Переходим на http://localhost:8080:
![](shots/ss7.png)
Входим:
![](shots/ss8.png)
Вот собственно наш пользователь:
![](shots/ss9.png)
## Разворачивание сервиса moodle
Содержимое файла `docker-compose.yml` в папке moodle:
```yaml
version: '2'
#Контейнер Mariadb используется как сервер для запуска
services:
mariadb:
image: docker.io/bitnami/mariadb:11.0
environment:
- ALLOW_EMPTY_PASSWORD=yes
- MARIADB_USER=bn_moodle
- MARIADB_DATABASE=bitnami_moodle
- MARIADB_CHARACTER_SET=utf8mb4
- MARIADB_COLLATE=utf8mb4_unicode_ci
volumes:
- 'mariadb_data:/bitnami/mariadb'
#Контейнер moodle используется для запуска самого сервиса
moodle:
image: docker.io/bitnami/moodle:4.2
ports: #порт
- '80:8080'
- '443:8443'
environment:
- MOODLE_DATABASE_HOST=mariadb
- MOODLE_DATABASE_PORT_NUMBER=3306
- MOODLE_DATABASE_USER=bn_moodle
- MOODLE_DATABASE_NAME=bitnami_moodle
- ALLOW_EMPTY_PASSWORD=yes
- MOODLE_USERNAME=vechno
- MOODLE_PASSWORD=solo
volumes:
- 'moodle_data:/bitnami/moodle'
- 'moodledata_data:/bitnami/moodledata'
depends_on:
- mariadb
volumes:
mariadb_data:
driver: local
moodle_data:
driver: local
moodledata_data:
driver: local
```
Далее в командной строке разворачиваем сервис командой `docker-compose up`:
![](shots/ss10.png)
Открываем Docker Desktop и проверяем, что контейнер сервера базы данных и moodle созданы и запущены:
![](shots/ss11.png)
Переходим на http://localhost:80:
![](shots/ss12.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Some files were not shown because too many files have changed in this diff Show More