This commit is contained in:
никита покладов
2025-03-23 01:36:44 +04:00
parent 4661f77f23
commit f637640a56
10 changed files with 383 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
# Отчёт по лабораторной работе №3
Разработка распределенного приложения с использованием фреймворка Spring Boot.
Действия по варианту должны производиться в LXC контейнерах. Необходимо разработать параллельный вариант алгоритма с применением сервис-ориентированного подхода и фреймворка Spring Boot, замерить время его работы.
## Вариант и задание
17 Упорядочить строки матрицы по убыванию суммы элементов.
## Как запустить лабораторную работу
1. развернуть три Worker-сервиса с разными IP-адресами и Master-сервис.
2. Установить **Java 17** и **Maven** в контейнерах.
3. Собрать и запустить сервисы с помощью Maven:
```sh
mvn clean package
java -jar target/master-0.0.1-SNAPSHOT.jar # Запуск Master
java -jar target/worker-0.0.1-SNAPSHOT.jar # Запуск Worker
```
4. Для запуска обработки выполнить GET-запрос к Master-сервису:
```sh
curl http://localhost:8080/start
```
## Архитектура приложения
Приложение состоит из двух типов сервисов:
- **Master** (главный сервер) — управляет процессом, делит входные данные и собирает результаты.
- **Worker** (рабочие узлы) — принимают данные, обрабатывают их и отправляют обратно на Master.
Общий процесс работы:
1. Master генерирует матрицу размером 1000x1000 со случайными значениями.
2. Матрица делится на три части, которые отправляются на три Worker-сервиса.
3. Каждый Worker вычисляет сумму элементов строк своей части матрицы и возвращает результаты.
4. Master собирает суммы, сортирует строки матрицы по убыванию суммы и измеряет время выполнения.
## Код Master
**`MasterApplication.java`** - основной класс Spring Boot-приложения для Master-сервиса:
```java
@SpringBootApplication
public class MasterApplication {
public static void main(String[] args) {
SpringApplication.run(MasterApplication.class, args);
}
}
```
**`MasterController.java`** - контроллер Master-сервиса:
- Генерирует матрицу.
- Делит на части и отправляет на Worker-сервисы.
- Собирает результаты, сортирует матрицу и измеряет время работы.
```java
@RestController
public class MasterController {
private final String[] workerUrls = {
"http://192.168.16.116:8081/calculateSum",
"http://192.168.16.117:8082/calculateSum",
"http://192.168.16.118:8083/calculateSum"
};
@Autowired
private RestTemplate restTemplate;
@GetMapping("/start")
public ResponseEntity<Map<String, Object>> start() {
long startTime = System.currentTimeMillis();
int[][] matrix = generateMatrix(1000, 1000);
int chunkSize = matrix.length / 3;
int[][] part1 = Arrays.copyOfRange(matrix, 0, chunkSize);
int[][] part2 = Arrays.copyOfRange(matrix, chunkSize, 2 * chunkSize);
int[][] part3 = Arrays.copyOfRange(matrix, 2 * chunkSize, matrix.length);
int[] sums1 = restTemplate.postForObject(workerUrls[0], part1, int[].class);
int[] sums2 = restTemplate.postForObject(workerUrls[1], part2, int[].class);
int[] sums3 = restTemplate.postForObject(workerUrls[2], part3, int[].class);
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
Map<String, Object> response = new HashMap<>();
response.put("durationMs", duration);
return ResponseEntity.ok(response);
}
}
```
## Код Worker
**`WorkerApplication.java`** - основной класс Spring Boot-приложения для Worker-сервиса:
```java
@SpringBootApplication
public class WorkerApplication {
public static void main(String[] args) {
SpringApplication.run(WorkerApplication.class, args);
}
}
```
**`WorkerController.java`** - контроллер Worker-сервиса, обрабатывает запросы Master-сервера:
```java
@RestController
public class WorkerController {
@PostMapping("/calculateSum")
public int[] calculateSum(@RequestBody int[][] matrixPart) {
int[] sums = new int[matrixPart.length];
for (int i = 0; i < matrixPart.length; i++) {
sums[i] = Arrays.stream(matrixPart[i]).sum();
}
return sums;
}
}
```
## Вывод программы
### Master
```
=== Генерация матрицы 1000x1000 завершена ===
=== Отправка данных на Worker Services ===
Отправка части 1 на Worker 1 (строки 0-332)"
Отправка части 2 на Worker 2 (строки 333-665)"
Отправка части 3 на Worker 3 (строки 666-999)"
=== Получение результатов от Worker Services ===
Результаты от Worker 1: 333 строк
Результаты от Worker 2: 333 строк
Результаты от Worker 3: 334 строк
=== Объединенные суммы строк ===
Всего сумм: 1000
=== Матрица отсортированна ===
=== Время выполнения ===
534 мс
```
### Worker
```
=== Получена часть матрицы для обработки ===
Количество строк: 333
Строка 0: сумма = 23511
Строка 1: сумма = 54312
Строка 2: сумма = 57424
...
Строка 320: сумма = 12564
Строка 321: сумма = 95643
Строка 322: сумма = 33422
=== Обработка завершена ===
```
## Выводы по работе
В ходе лабораторной работы было реализовано распределённое приложение на основе Spring Boot, использующее сервис-ориентированную архитектуру для параллельной обработки данных. Spring Boot + REST API обеспечивает простоту разработки и масштабируемость, но уступает Apache Ignite и MPI в производительности из-за сетевых накладных расходов. Apache Ignite оптимизирован для распределённых вычислений и работы с большими данными, а MPI обеспечивает максимальную эффективность за счёт прямого обмена сообщениями, но сложен в реализации. Выбор зависит от приоритета между удобством и вычислительной мощностью.

View File

@@ -0,0 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>master</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,11 @@
package com.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,108 @@
package com.example.master;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class MasterController {
private final String[] workerUrls = {
"http://192.168.16.116:8081/calculateSum",
"http://192.168.16.117:8082/calculateSum",
"http://192.168.16.118:8083/calculateSum"
};
@Autowired
private RestTemplate restTemplate;
@GetMapping("/start")
public ResponseEntity<Map<String, Object>> start() {
long startTime = System.currentTimeMillis();
// Генерация матрицы 1000x1000
int[][] matrix = generateMatrix(1000, 1000);
System.out.println("=== Генерация матрицы 1000x1000 завершена ===");
// Разделение матрицы на 3 части
int chunkSize = matrix.length / 3;
int[][] part1 = Arrays.copyOfRange(matrix, 0, chunkSize);
int[][] part2 = Arrays.copyOfRange(matrix, chunkSize, 2 * chunkSize);
int[][] part3 = Arrays.copyOfRange(matrix, 2 * chunkSize, matrix.length);
System.out.println("\n=== Отправка данных на Worker Services ===");
System.out.println("Отправка части 1 на Worker 1 (строки 0-" + (chunkSize - 1) + ")");
System.out.println("Отправка части 2 на Worker 2 (строки " + chunkSize + "-" + (2 * chunkSize - 1) + ")");
System.out.println("Отправка части 3 на Worker 3 (строки " + (2 * chunkSize) + "-" + (matrix.length - 1) + ")");
// Отправка частей на Worker Services
int[] sums1 = restTemplate.postForObject(workerUrls[0], part1, int[].class);
int[] sums2 = restTemplate.postForObject(workerUrls[1], part2, int[].class);
int[] sums3 = restTemplate.postForObject(workerUrls[2], part3, int[].class);
System.out.println("\n=== Получение результатов от Worker Services ===");
System.out.println("Результаты от Worker 1: " + sums1.length + " строк");
System.out.println("Результаты от Worker 2: " + sums2.length + " строк");
System.out.println("Результаты от Worker 3: " + sums3.length + " строк");
// Объединение результатов
int[] allSums = new int[matrix.length];
System.arraycopy(sums1, 0, allSums, 0, sums1.length);
System.arraycopy(sums2, 0, allSums, sums1.length, sums2.length);
System.arraycopy(sums3, 0, allSums, sums1.length + sums2.length, sums3.length);
System.out.println("\n=== Объединенные суммы строк ===");
System.out.println("Всего сумм: " + allSums.length);
// Сортировка матрицы по убыванию суммы строк
sortMatrixBySum(matrix, allSums);
System.out.println("\n=== Матрица отсортированна ===");
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("\n=== Время выполнения ===");
System.out.println(duration + " мс");
Map<String, Object> response = new HashMap<>();
response.put("durationMs", duration);
return ResponseEntity.ok(response);
}
private int[][] generateMatrix(int rows, int cols) {
Random random = new Random();
int[][] matrix = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = random.nextInt(100); // Заполняем случайными числами от 0 до 99
}
}
return matrix;
}
private void sortMatrixBySum(int[][] matrix, int[] sums) {
for (int i = 0; i < sums.length - 1; i++) {
for (int j = 0; j < sums.length - i - 1; j++) {
if (sums[j] < sums[j + 1]) {
// Меняем местами суммы
int tempSum = sums[j];
sums[j] = sums[j + 1];
sums[j + 1] = tempSum;
// Меняем местами строки матрицы
int[] tempRow = matrix[j];
matrix[j] = matrix[j + 1];
matrix[j + 1] = tempRow;
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
package com.example.master;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@@ -0,0 +1 @@
server.port=8080

View File

@@ -0,0 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>worker</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,11 @@
package com.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,26 @@
package com.example.worker;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
@RestController
public class WorkerController {
@PostMapping("/calculateSum")
public int[] calculateSum(@RequestBody int[][] matrixPart) {
System.out.println("\n=== Получена часть матрицы для обработки ===");
System.out.println("Количество строк: " + matrixPart.length);
int[] sums = new int[matrixPart.length];
for (int i = 0; i < matrixPart.length; i++) {
sums[i] = Arrays.stream(matrixPart[i]).sum();
System.out.println("Строка " + i + ": сумма = " + sums[i]);
}
System.out.println("=== Обработка завершена ===");
return sums;
}
}

View File

@@ -0,0 +1 @@
server.port=8081