Лаба №3

This commit is contained in:
2025-03-30 23:26:00 +04:00
parent 373ad2c379
commit d562d2f652
9 changed files with 471 additions and 0 deletions

View File

@@ -0,0 +1,240 @@
# Лабораторная работа №3
Разработка распределенного приложения с использованием фреймворка Spring Boot. Действия по варианту должны производиться
в LXC контейнерах. Необходимо разработать параллельный вариант алгоритма с применением сервис-ориентированного подхода и
фреймворка Spring Boot, замерить время его работы.
## Вариант и задание
2. Разделить элементы матрицы на наименьший элемент.
## Как запустить лабораторную работу
1. Установить **Java 17** и **Maven** в каждом контейнере.
2. Поставить на два контейнера из трёх копии Worker-service
3. На главный контейнер поставить Master-service
4. В сегменте кода MasterController прописать IP контейнеров с Worker-service и порт, прописанный в application.properties
```
System.out.println("{Master} Отправка частей матрицы работникам...");
double[] result1 = restTemplate.postForObject("http://192.168.26.128:8081/process",
new Matrix(part1, min), double[].class);
double[] result2 = restTemplate.postForObject("http://192.168.26.129:8081/process",
new Matrix(part2, min), double[].class);
```
5. Собрать и запустить Master-service в главном контейнере:
```
mvn clean package
java -jar target/master-0.0.1-SNAPSHOT.jar
```
6. Собрать и запустить Worker-service в остальных контейнерах
```
mvn clean package
java -jar target/worker-0.0.1-SNAPSHOT.jar
```
5. Запустить обработки выполнить GET-запрос в виртуальной машине, в которой находятся контейнеры, к Master-сервису:
```
curl http://localhost:8080/start
```
## Что делает
Master-servise находит наименьший элемент в матрице, делит матрицу на части, и распределяет их по контейнерам с
Worker-service, где происходит деление частей матрицы на наименьший элемент. После части матрицы отправляются обратно и
собираются.
## Описание кода
### 1. MasterController.java
```
package org.example.master;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Random;
@RestController
@RequestMapping("/master")
public class MasterController
{
int arraySize = 1000;
private final RestTemplate restTemplate = new RestTemplate();
@PostMapping("/process")
public double process()
{
long startTime = System.nanoTime();
System.out.println("{Master} Генерация матрицы...");
double[][] matrix = generateMatrix();
double[] flatMatrix = flattenMatrix(matrix);
System.out.println("{Master} Поиск наименьшего элемента...");
double min = Arrays.stream(flatMatrix).min().orElse(Double.NaN);
System.out.println("{Master} Наименьший элемент: " + min);
System.out.println("{Master} Разделение матрицы на части...");
int halfSize = (arraySize * arraySize) / 2;
double[] part1 = Arrays.copyOfRange(flatMatrix, 0, halfSize);
double[] part2 = Arrays.copyOfRange(flatMatrix, halfSize, arraySize * arraySize);
System.out.println("{Master} Отправка частей матрицы работникам...");
double[] result1 = restTemplate.postForObject("http://192.168.26.128:8081/process",
new Matrix(part1, min), double[].class);
double[] result2 = restTemplate.postForObject("http://192.168.26.129:8081/process",
new Matrix(part2, min), double[].class);
System.out.println("{Master} Сборка матрицы из частей...");
double[] resultMatrix = new double[arraySize * arraySize];
System.arraycopy(result1, 0, resultMatrix, 0, result1.length);
System.arraycopy(result2, 0, resultMatrix, result1.length, result2.length);
double[][] finalMatrix = unflattenMatrix(resultMatrix, arraySize);
long endTime = System.nanoTime();
long time = (endTime - startTime) / 1000000;
System.out.println("{Master} Вычисления завершены. Время: " + time + " мс");
return time;
}
static class Matrix
{
public double[] matrix;
public double min;
public Matrix(double[] matrix, double min)
{
this.matrix = matrix;
this.min = min;
}
}
private double[][] generateMatrix()
{
Random random = new Random();
double[][] matrix = new double[arraySize][arraySize];
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < arraySize; j++)
{
matrix[i][j] = random.nextInt(-1000000 , 1000000);
}
}
return matrix;
}
private double[] flattenMatrix(double[][] matrix)
{
return Arrays.stream(matrix).flatMapToDouble(Arrays::stream).toArray();
}
private double[][] unflattenMatrix(double[] array, int arraySize)
{
double[][] matrix = new double[arraySize][arraySize];
for (int i = 0; i < arraySize; i++)
{
System.arraycopy(array, i * arraySize, matrix[i], 0, arraySize);
}
return matrix;
}
}
```
MasterController: Основной контроллер, который обрабатывает запросы на /master/process.
processMatrix(): Метод, который генерирует матрицу, находит наименьший элемент, делит матрицу на две части и
отправляет их воркерам для обработки.
MatrixTask: Внутренний класс, который используется для передачи данных (часть матрицы и наименьший элемент) между Master
и Worker.
generateMatrix(): Метод для генерации квадратной матрицы со случайными значениями.
flattenMatrix(): Метод, который преобразует двумерную матрицу в одномерный массив.
unflattenMatrix(): Метод, который преобразует одномерный массив обратно в двумерную матрицу заданного размера.
### 2. WorkerApplication.java
```
package org.example.pr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WorkerApplication {
public static void main(String[] args) {
SpringApplication.run(WorkerApplication.class, args);
}
}
```
WorkerApplication: Основной класс для запуска приложения Worker. Использует аннотацию @SpringBootApplication для
автоматической конфигурации Spring Boot.
### 3. WorkerController.java
```
package org.example.worker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Random;
@RestController
public class WorkerController
{
@PostMapping("/process")
public double[] processMatrix(@RequestBody MatrixTask task)
{
double[] matrix = task.matrix;
double min = task.min;
System.out.println("{Worker} Данные получены");
System.out.println("{Worker} Деление матрицы на наименьший элемент...");
for (int i = 0; i < matrix.length; i++) matrix[i] /= min;
System.out.println("{Worker} Деление матрицы завершено.");
return matrix;
}
static class Matrix
{
public double[] matrix;
public double min;
public Matrix(double[] matrix, double min)
{
this.matrix = matrix;
this.min = min;
}
}
}
```
WorkerController: Контроллер, который обрабатывает запросы на /process.
processMatrix(): Метод, который принимает задачу от Master, обрабатывает матрицу, деля каждый элемент на наименьший элемент,
и возвращает результат.
MatrixTask: Внутренний класс, который используется для получения данных от Master.
## Вывод программы
### Master
```
{Мастер} Генерация матрицы...
{Мастер} Поиск наименьшего элемента...
{Мастер} Наименьший элемент: -1000000.0
{Мастер} Разделение матрицы на части...
{Мастер} Отправка частей матрицы работникам...
{Мастер} Сборка матрицы из частей...
{Мастер} Вычисления завершены. Время: 5512 мс
```
### Worker
```
{Worker} Данные получены
{Worker} Деление матрицы на наименьший элемент...
{Worker} Деление матрицы завершено.
```
## Выводы по работе
В ходе лабораторной работы было разработано распределённое приложение
на основе Spring Boot, которое использует сервис-ориентированную архитектуру
для параллельной обработки данных. Spring Boot оказался куда медленнее MPI и ThreadPoolExecutor/ForkJoinPool. Накладные
расходы на HTTP-запросы, передача данных по сети увеличивает время выполнения, также управление потоками в MPI и
специализированных библиотеках более эффективно, так как они оптимизированы для параллельной обработки.

View File

@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@@ -0,0 +1,12 @@
package org.example.master;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MasterApplication
{
public static void main(String[] args)
{
SpringApplication.run(MasterApplication.class, args);
}
}

View File

@@ -0,0 +1,93 @@
package org.example.master;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Random;
@RestController
@RequestMapping("/master")
public class MasterController
{
int arraySize = 1000;
private final RestTemplate restTemplate = new RestTemplate();
@PostMapping("/process")
public double process()
{
long startTime = System.nanoTime();
System.out.println("{Master} Генерация матрицы...");
double[][] matrix = generateMatrix();
double[] flatMatrix = flattenMatrix(matrix);
System.out.println("{Master} Поиск наименьшего элемента...");
double min = Arrays.stream(flatMatrix).min().orElse(Double.NaN);
System.out.println("{Master} Наименьший элемент: " + min);
System.out.println("{Master} Разделение матрицы на части...");
int halfSize = (arraySize * arraySize) / 2;
double[] part1 = Arrays.copyOfRange(flatMatrix, 0, halfSize);
double[] part2 = Arrays.copyOfRange(flatMatrix, halfSize, arraySize * arraySize);
System.out.println("{Master} Отправка частей матрицы работникам...");
double[] result1 = restTemplate.postForObject("http://192.168.26.128:8081/process",
new Matrix(part1, min), double[].class);
double[] result2 = restTemplate.postForObject("http://192.168.26.129:8081/process",
new Matrix(part2, min), double[].class);
System.out.println("{Master} Сборка матрицы из частей...");
double[] resultMatrix = new double[arraySize * arraySize];
System.arraycopy(result1, 0, resultMatrix, 0, result1.length);
System.arraycopy(result2, 0, resultMatrix, result1.length, result2.length);
double[][] finalMatrix = unflattenMatrix(resultMatrix, arraySize);
long endTime = System.nanoTime();
long time = (endTime - startTime) / 1000000;
System.out.println("{Master} Вычисления завершены. Время: " + time + " мс");
return time;
}
static class Matrix
{
public double[] matrix;
public double min;
public Matrix(double[] matrix, double min)
{
this.matrix = matrix;
this.min = min;
}
}
private double[][] generateMatrix()
{
Random random = new Random();
double[][] matrix = new double[arraySize][arraySize];
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < arraySize; j++)
{
matrix[i][j] = random.nextInt(-1000000 , 1000000);
}
}
return matrix;
}
private double[] flattenMatrix(double[][] matrix)
{
return Arrays.stream(matrix).flatMapToDouble(Arrays::stream).toArray();
}
private double[][] unflattenMatrix(double[] array, int arraySize)
{
double[][] matrix = new double[arraySize][arraySize];
for (int i = 0; i < arraySize; i++)
{
System.arraycopy(array, i * arraySize, matrix[i], 0, arraySize);
}
return matrix;
}
}

View File

@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@@ -0,0 +1,12 @@
package org.example.worker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WorkerApplication
{
public static void main(String[] args)
{
SpringApplication.run(WorkerApplication.class, args);
}
}

View File

@@ -0,0 +1,36 @@
package org.example.worker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Random;
@RestController
public class WorkerController
{
@PostMapping("/process")
public double[] processMatrix(@RequestBody MatrixTask task)
{
double[] matrix = task.matrix;
double min = task.min;
System.out.println("{Worker} Данные получены");
System.out.println("{Worker} Деление матрицы на наименьший элемент...");
for (int i = 0; i < matrix.length; i++) matrix[i] /= min;
System.out.println("{Worker} Деление матрицы завершено.");
return matrix;
}
static class Matrix
{
public double[] matrix;
public double min;
public Matrix(double[] matrix, double min)
{
this.matrix = matrix;
this.min = min;
}
}
}