lab 3
This commit is contained in:
149
pokladov_nikita_lab_3/README.md
Normal file
149
pokladov_nikita_lab_3/README.md
Normal 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 обеспечивает максимальную эффективность за счёт прямого обмена сообщениями, но сложен в реализации. Выбор зависит от приоритета между удобством и вычислительной мощностью.
|
||||||
|
|
||||||
31
pokladov_nikita_lab_3/master/pom.xml
Normal file
31
pokladov_nikita_lab_3/master/pom.xml
Normal 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>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
server.port=8080
|
||||||
31
pokladov_nikita_lab_3/worker/pom.xml
Normal file
31
pokladov_nikita_lab_3/worker/pom.xml
Normal 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>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
server.port=8081
|
||||||
Reference in New Issue
Block a user