Forgot Readme ))
This commit is contained in:
325
savinov_roman_lab_4/README.md
Normal file
325
savinov_roman_lab_4/README.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# Лабораторная №4
|
||||
Разработка распределенного приложения с использованием платформы Apache Ignite.
|
||||
Необходимо разработать параллельный вариант алгоритма с применением подхода Grid
|
||||
Gain и платформа Apache Ignite, замерить время его работы.
|
||||
## Вариант и задание
|
||||
22 Упорядочить столбцы матрицы по возрастанию первых элементов.
|
||||
## Что программа делает
|
||||
|
||||
- **MatrixSortingTask** распределяет работу по сортировке столбцов между узлами.
|
||||
- Каждый узел выполняет сортировку своих столбцов с помощью **ColumnSortJob**.
|
||||
- После завершения сортировки результаты агрегации собираются и объединяются в итоговую отсортированную матрицу.
|
||||
|
||||
Таким образом, задача сортировки матрицы с помощью распределённой обработки на кластере Apache Ignite.
|
||||
|
||||
|
||||
## Описание кода
|
||||
|
||||
### **MatrixSortingTask** (Задача сортировки матрицы)
|
||||
|
||||
Этот класс отвечает за распределение работы по сортировке матрицы на несколько узлов Apache Ignite и последующую агрегацию результатов.
|
||||
|
||||
#### **Основные моменты**:
|
||||
|
||||
1. **Распределение работы**:
|
||||
- Задача делит столбцы матрицы между несколькими узлами кластера для параллельной сортировки.
|
||||
- Каждый узел сортирует определённые столбцы матрицы.
|
||||
|
||||
2. **Реализация метода `map`**:
|
||||
- Метод `map` делит работу на несколько частей (по столбцам).
|
||||
- Для каждого узла создаётся задание (задача сортировки столбцов), которое будет обрабатываться этим узлом.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> nodes, int[][] matrix) {
|
||||
int cols = matrix[0].length;
|
||||
int nodeCount = nodes.size();
|
||||
int chunkSize = (int) Math.ceil((double) cols / nodeCount);
|
||||
|
||||
Map<ComputeJob, ClusterNode> map = new HashMap<>();
|
||||
|
||||
// Разбиваем работу на части по столбцам
|
||||
for (int i = 0; i < nodeCount; i++) {
|
||||
int startCol = i * chunkSize;
|
||||
int endCol = Math.min(startCol + chunkSize, cols);
|
||||
int[][] subMatrix = extractColumns(matrix, startCol, endCol);
|
||||
map.put(new ColumnSortJob(subMatrix, startCol), nodes.get(i));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
```
|
||||
|
||||
- **`map`**:
|
||||
- Вычисляется количество узлов и делится матрица на части (столбцы), которые будут обработаны каждым узлом.
|
||||
- Создаётся задание `ColumnSortJob` для каждого узла с подматрицей столбцов и индексом начала сортируемых столбцов.
|
||||
|
||||
3. **Агрегация результатов**:
|
||||
- После того как каждый узел завершит свою работу (сортировку столбцов), результаты собираются в одном методе `reduce`.
|
||||
- Все отсортированные части матрицы объединяются в итоговую отсортированную матрицу.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public int[][] reduce(List<ComputeJobResult> results) {
|
||||
int[][] sortedMatrix = new int[results.get(0).getData().length][];
|
||||
int currentCol = 0;
|
||||
|
||||
for (ComputeJobResult result : results) {
|
||||
int[][] sortedChunk = (int[][]) result.getData();
|
||||
mergeColumns(sortedMatrix, sortedChunk, currentCol);
|
||||
currentCol += sortedChunk[0].length;
|
||||
}
|
||||
return sortedMatrix;
|
||||
}
|
||||
```
|
||||
|
||||
- **`reduce`**:
|
||||
- Объединяет отсортированные столбцы из разных узлов в единую матрицу.
|
||||
- Метод `mergeColumns` копирует данные из отсортированных частей в итоговую матрицу.
|
||||
|
||||
4. **Дополнительные методы**:
|
||||
- **`extractColumns`**: Извлекает подматрицу столбцов для конкретного узла.
|
||||
- **`mergeColumns`**: Объединяет отсортированные столбцы в итоговую матрицу.
|
||||
|
||||
```java
|
||||
private int[][] extractColumns(int[][] matrix, int startCol, int endCol) {
|
||||
// Извлекает столбцы с startCol по endCol
|
||||
}
|
||||
|
||||
private void mergeColumns(int[][] target, int[][] sortedChunk, int startCol) {
|
||||
// Объединяет отсортированные столбцы с основной матрицей
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **ColumnSortJob** (Задача сортировки столбцов)
|
||||
|
||||
Этот класс представляет собой задачу для одного узла кластера, которая выполняет сортировку столбцов подматрицы.
|
||||
|
||||
#### **Основные моменты**:
|
||||
|
||||
1. **Сортировка столбцов**:
|
||||
- Каждый узел получает подматрицу и сортирует столбцы этой подматрицы.
|
||||
- Для сортировки используется массив индексов, который определяет порядок столбцов после сортировки.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public Object execute() {
|
||||
Integer[] indices = new Integer[cols];
|
||||
for (int i = 0; i < cols; i++) indices[i] = i;
|
||||
|
||||
// Сортируем столбцы по значениям первого ряда
|
||||
Arrays.sort(indices, Comparator.comparingInt(a -> matrix[0][a]));
|
||||
|
||||
int[][] sortedMatrix = new int[rows][cols];
|
||||
for (int i = 0; i < cols; i++) {
|
||||
for (int j = 0; j < rows; j++) {
|
||||
sortedMatrix[j][i] = matrix[j][indices[i]];
|
||||
}
|
||||
}
|
||||
return sortedMatrix;
|
||||
}
|
||||
```
|
||||
|
||||
- **`execute`**:
|
||||
- Столбцы подматрицы сортируются с использованием `Arrays.sort` по первому элементу каждого столбца.
|
||||
- Индексы столбцов в массиве `indices` определяют новый порядок столбцов после сортировки.
|
||||
- Возвращается отсортированная матрица.
|
||||
|
||||
2. **Отмена задачи**:
|
||||
- Метод `cancel` вызывается, если задача была прервана, но в данном примере он просто выводит сообщение.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void cancel() {
|
||||
System.out.println("ColumnSortJob cancelled.");
|
||||
}
|
||||
```
|
||||
|
||||
3. **Конструктор**:
|
||||
- При создании объекта передаются подматрица и индекс начала столбцов, чтобы корректно обработать каждый сегмент матрицы.
|
||||
|
||||
```java
|
||||
public ColumnSortJob(int[][] matrix, int startCol) {
|
||||
this.matrix = matrix;
|
||||
this.startCol = startCol;
|
||||
}
|
||||
```
|
||||
|
||||
## Как запустить
|
||||
Для успешной работы потребуется конфигурация ignite.xml. Она должна выглядеть примерно так
|
||||
```xml
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
|
||||
<!-- Включаем или отключаем загрузку классов между узлами -->
|
||||
<property name="peerClassLoadingEnabled" value="true"/>
|
||||
|
||||
<property name="discoverySpi">
|
||||
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
|
||||
<property name="ipFinder">
|
||||
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
|
||||
<!-- Список адресов для обнаружения узлов -->
|
||||
<property name="addresses">
|
||||
<list>
|
||||
<value>IP_CONTAINER1:port</value>
|
||||
<value>IP_CONTAINER2:port</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</beans>
|
||||
```
|
||||
# Основные свойства:
|
||||
1. **peerClassLoadingEnabled** — разрешает или запрещает загрузку классов между узлами кластера.
|
||||
2. **discoverySpi** — настройка компонента для поиска и подключения других узлов.
|
||||
3. **TcpDiscoverySpi** — механизм для обнаружения узлов по TCP.
|
||||
4. **ipFinder** — хранит список адресов, используемых для поиска узлов.
|
||||
5. **TcpDiscoveryVmIpFinder** — класс, который указывает список IP-адресов для поиска узлов.
|
||||
6. **addresses** — конкретные адреса, которые используются для подключения узлов к кластеру.
|
||||
|
||||
Необходимые зависимости
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.ignite</groupId>
|
||||
<artifactId>ignite-core</artifactId>
|
||||
<version>2.17.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Ignite Spring -->
|
||||
<dependency>
|
||||
<groupId>org.apache.ignite</groupId>
|
||||
<artifactId>ignite-spring</artifactId>
|
||||
<version>2.17.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Плагин для сборки Fat JAR -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>main.java.com.example.MainTask</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
```
|
||||
После сборки в папке target (по умолчанию такая) должен появится .jar файл с необходимыми классами
|
||||
Его уже и нужно будет запустить на компьютере
|
||||
|
||||
У меня этот файл называется savinov_roman_lab_4-1.0-SNAPSHOT.jar
|
||||
|
||||
На втором контейнере я установил платформу apache ignite и запустил её.
|
||||
(предварительно нужно изменить default-config.xml)
|
||||
|
||||
```bash
|
||||
cd workingDirectory
|
||||
java -jar savinov_roman_lab_4-1.0-SNAPSHOT.jar
|
||||
```
|
||||
## Выходное значение для матрицы размером 3000 на 3000
|
||||
Главная нода
|
||||
```Главная нода.
|
||||
[14:54:37] Ignite node started OK (id=4c43f1a7)
|
||||
[14:54:37] Topology snapshot [ver=8, locNode=4c43f1a7, servers=2, clients=0, state=ACTIVE, CPUs=4, offheap=1.5GB, heap=1.9GB]
|
||||
[14:54:37] ^-- Baseline [id=0, size=2, online=2, offline=0]
|
||||
Ignite started successfully.
|
||||
Random matrix generated.
|
||||
Original Matrix:
|
||||
18 39 26 96 45 81 87 91 6 19
|
||||
5 98 93 68 14 16 41 81 6 46
|
||||
37 48 30 49 72 21 69 24 38 7
|
||||
95 41 76 83 94 53 66 99 39 47
|
||||
95 13 70 92 49 45 75 0 58 81
|
||||
82 43 50 1 66 40 55 66 94 54
|
||||
92 95 71 72 23 58 89 18 49 75
|
||||
77 36 96 49 26 20 0 63 97 24
|
||||
2 23 50 89 14 46 39 14 57 16
|
||||
31 75 88 94 28 46 44 40 92 74
|
||||
Mapping jobs to nodes. Total nodes: 2
|
||||
Sorting columns starting from index 1500
|
||||
Sorting complete for columns starting at index 1500
|
||||
Reducing results from jobs. Number of results: 2
|
||||
Sorted Matrix:
|
||||
0 0 0 0 0 0 0 0 0 0
|
||||
2 62 56 61 71 93 18 39 55 49
|
||||
48 22 46 38 47 69 27 23 37 87
|
||||
8 54 90 39 29 0 6 54 94 60
|
||||
61 7 43 39 37 13 15 85 35 79
|
||||
71 12 19 12 40 50 74 63 54 31
|
||||
47 20 68 45 43 32 56 59 50 2
|
||||
36 15 60 12 67 52 88 57 54 8
|
||||
52 40 54 17 67 80 5 27 45 18
|
||||
30 23 18 78 98 49 45 83 5 43
|
||||
Time taken: 1275 ms
|
||||
[14:54:38] Ignite node stopped OK [uptime=00:00:01.806]
|
||||
|
||||
```
|
||||
Нода работник
|
||||
```Нода Работник
|
||||
[14:54:36] ^-- Baseline [id=0, size=2, online=2, offline=0]
|
||||
Sorting columns starting from index 0
|
||||
Sorting complete for columns starting at index 0
|
||||
[14:54:38] Topology snapshot [ver=9, locNode=8e88275c, servers=1, clients=0, state=ACTIVE, CPUs=2, offheap=0.77GB, heap=0.96GB]
|
||||
[14:54:38] ^-- Baseline [id=0, size=1, online=1, offline=0]
|
||||
[14:55:00]
|
||||
[14:55:00] ^-- sysMemPlc region [type=internal, persistence=false, lazyAlloc=false,
|
||||
[14:55:00] ... initCfg=40MB, maxCfg=100MB, usedRam=0MB, freeRam=99.21%, allocRam=40MB]
|
||||
[14:55:00] ^-- default region [type=default, persistence=false, lazyAlloc=true,
|
||||
[14:55:00] ... initCfg=256MB, maxCfg=783MB, usedRam=0MB, freeRam=100%, allocRam=0MB]
|
||||
[14:55:00] ^-- volatileDsMemPlc region [type=user, persistence=false, lazyAlloc=true,
|
||||
[14:55:00] ... initCfg=40MB, maxCfg=100MB, usedRam=0MB, freeRam=100%, allocRam=0MB]
|
||||
[14:55:00]
|
||||
[14:55:00]
|
||||
[14:55:00] Data storage metrics for local node (to disable set 'metricsLogFrequency' to 0)
|
||||
[14:55:00] ^-- Off-heap memory [used=0MB, free=99.92%, allocated=40MB]
|
||||
[14:55:00] ^-- Page memory [pages=200]
|
||||
[14:56:00]
|
||||
[14:56:00] ^-- sysMemPlc region [type=internal, persistence=false, lazyAlloc=false,
|
||||
[14:56:00] ... initCfg=40MB, maxCfg=100MB, usedRam=0MB, freeRam=99.21%, allocRam=40MB]
|
||||
[14:56:00] ^-- default region [type=default, persistence=false, lazyAlloc=true,
|
||||
[14:56:00] ... initCfg=256MB, maxCfg=783MB, usedRam=0MB, freeRam=100%, allocRam=0MB]
|
||||
[14:56:00] ^-- volatileDsMemPlc region [type=user, persistence=false, lazyAlloc=true,
|
||||
[14:56:00] ... initCfg=40MB, maxCfg=100MB, usedRam=0MB, freeRam=100%, allocRam=0MB]
|
||||
[14:56:00]
|
||||
|
||||
```
|
||||
# Вывод
|
||||
Контейнеры смогли эффективно взаимодействовать между собой благодаря
|
||||
использованию
|
||||
механизма
|
||||
Peer Class Loader в Apache Ignite, который обеспечивал обмен данными и слаженную
|
||||
работу распределённой системы. Однако эффективность сортировки данных зависела от
|
||||
качества сети, поскольку передача данных по сети добавляла издержки, что могло замедлить
|
||||
процесс обработки, особенно при большом количестве узлов.
|
||||
Reference in New Issue
Block a user