Лаба №3
This commit is contained in:
240
khasyanov_aidar_lab_3/README.md
Normal file
240
khasyanov_aidar_lab_3/README.md
Normal 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 и
|
||||
специализированных библиотеках более эффективно, так как они оптимизированы для параллельной обработки.
|
||||
38
khasyanov_aidar_lab_3/SSPR_LAB_3/Master-service/.gitignore
vendored
Normal file
38
khasyanov_aidar_lab_3/SSPR_LAB_3/Master-service/.gitignore
vendored
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
server.port=8080
|
||||
38
khasyanov_aidar_lab_3/SSPR_LAB_3/Worker-service/.gitignore
vendored
Normal file
38
khasyanov_aidar_lab_3/SSPR_LAB_3/Worker-service/.gitignore
vendored
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
server.port=8081
|
||||
Reference in New Issue
Block a user