Forgot Readme ))

This commit is contained in:
zum
2025-03-15 22:46:33 +04:00
parent 73d683f0bb
commit 8b41f34b95

View 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, который обеспечивал обмен данными и слаженную
работу распределённой системы. Однако эффективность сортировки данных зависела от
качества сети, поскольку передача данных по сети добавляла издержки, что могло замедлить
процесс обработки, особенно при большом количестве узлов.