Лабораторная работа 3
1. Задание
Разработка распределённого приложения с использованием Spring Boot.
Нужно реализовать параллельный вариант алгоритма с применением сервис-ориентированного подхода, замерить время работы алгоритма и распределить функционал между двумя сервисами:
- Compute Service: Находит минимальный элемент матрицы ниже главной диагонали.
- Gateway Service: Принимает запросы от клиента и пересылает их на Compute Service.
Вариант: Определить минимальный элемент матрицы ниже главной диагонали.
2. Описание кода
Приложение состоит из двух частей, каждая из которых – отдельное Spring Boot приложение.
2.1. Compute Service
Этот сервис отвечает за вычисления. Он принимает матрицу, запускает алгоритм поиска минимального элемента ниже главной диагонали, замеряет время выполнения и возвращает результат.
MatrixComputeApplication.java
package ru.kuznec;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MatrixComputeApplication {
public static void main(String[] args) {
SpringApplication.run(MatrixComputeApplication.class, args);
}
}
MatrixComputeController.java
package ru.kuznec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class MatrixComputeController {
@Autowired
private MatrixMinService matrixMinService;
@PostMapping("/computeMin")
public ResponseEntity<Map<String, Object>> computeMin(@RequestBody int[][] matrix) {
long startTime = System.nanoTime();
int min = matrixMinService.findMinBelowMainDiagonal(matrix);
long endTime = System.nanoTime();
double duration = (double) (endTime - startTime) / 1_000_000;
Map<String, Object> response = new HashMap<>();
response.put("minValue", min);
response.put("durationMs", duration);
return ResponseEntity.ok(response);
}
}
MatrixMinService.java
package ru.kuznec;
import org.springframework.stereotype.Service;
import java.util.stream.IntStream;
@Service
public class MatrixMinService {
public int findMinBelowMainDiagonal(int[][] matrix) {
return IntStream.range(1, matrix.length)
.parallel()
.map(i -> {
int rowMin = Integer.MAX_VALUE;
for (int j = 0; j < i; j++) {
if (matrix[i][j] < rowMin) {
rowMin = matrix[i][j];
}
}
return rowMin;
})
.min()
.orElse(Integer.MAX_VALUE);
}
}
2.2. Gateway Service
Этот сервис принимает клиентские запросы на эндпоинте /findMin и пересылает их на Compute Service. В настройках Gateway указан URL Compute Service с его IP-адресом (в нашем случае, например, http://192.168.10.101:8080/computeMin).
MatrixGatewayApplication.java
package ru.kuznec;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MatrixGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(MatrixGatewayApplication.class, args);
}
}
MatrixGatewayController.java
package ru.kuznec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@RestController
public class MatrixGatewayController {
@Autowired
private RestTemplate restTemplate;
// Адрес Compute Service (IP контейнера с Compute Service)
private String computeServiceUrl = "http://192.168.10.101:8080/computeMin";
@PostMapping("/findMin")
public ResponseEntity<?> findMin(@RequestBody int[][] matrix) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<int[][]> request = new HttpEntity<>(matrix, headers);
ResponseEntity<Map> response = restTemplate.exchange(
computeServiceUrl,
HttpMethod.POST,
request,
Map.class
);
return response;
}
}
RestTemplateConfig.java
package ru.kuznec;
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();
}
}
3. Запуск приложения
Сборка каждого приложения приводит к созданию jar-файлов. Запускаем их на разных контейнерах:
-
Compute Service:
На контейнере с IP192.168.10.101запускаем:java -jar Lab-3.jar --server.port=8080Compute Service будет доступен по адресу:
http://192.168.10.101:8080/computeMin -
Gateway Service:
На контейнере с IP192.168.10.102запускаем:java -jar Lab-3.1.jar --server.port=8081Gateway Service будет доступен по адресу:
http://192.168.10.102:8081/findMin
Gateway Service перенаправляет запросы на Compute Service по указанному адресу.
4. Проверка работы
Для проверки работы можно использовать curl, отправив запрос на Gateway Service:
curl -X POST http://192.168.10.102:8081/findMin \
-H "Content-Type: application/json" \
-d '[[5, 3, 8], [2, 6, 4], [7, 1, 9]]'
В ответ вы получите JSON с полями minValue (минимальное значение) и durationMs (время выполнения алгоритма в миллисекундах).