Балансировка нагрузки#
DataGrid автоматически балансирует нагрузку по заданиям, которые запускаются вычислительными задачами, и по отдельным задачам, отправленным с помощью API распределенных вычислений. Отдельные задачи, которые отправляются с помощью IgniteCompute.run(…) и других вычислительных методов, рассматриваются как задачи (task) с одним заданием (job).
По умолчанию DataGrid использует циклический (Round Robin) алгоритм RoundRobinLoadBalancingSpi, который в последовательном порядке распределяет задания по узлам, указанным для вычислительной задачи.
Важно
Балансировка нагрузки не относится к коллоцированным вычислениям.
Алгоритм балансировки нагрузки контролируется свойством IgniteConfiguration.loadBalancingSpi.
Циклический алгоритм балансировки нагрузки#
RoundRobinLoadBalancingSpi выполняет циклическую итерацию по доступным узлам и выбирает следующий в последовательности узел. Доступные узлы определяются при получении вычислительного экземпляра, с помощью которого выполняются задачи (подробнее о нем написано в разделе «Распределенные вычисления»).
Циклическая балансировка нагрузки поддерживает два режима операций: по задачам и глобальный.
При настроенном режиме по задачам реализация выбирает случайный узел в начале выполнения каждой задачи и последовательно выполняет итерацию по всем узлам топологии, начиная с выбранного. Когда общее число частей задачи совпадает с количеством узлов, режим гарантирует, что в выполнении задания будут участвовать все узлы.
Важно
Для режима по задачам нужно разрешить использование следующих типов событий:
EVT_TASK_FAILED,EVT_TASK_FINISHEDиEVT_JOB_MAPPED.
При настроенном глобальном режиме для всех задач поддерживается одна последовательная очередь узлов. Каждый раз выбирается следующий узел в очереди. Если в этом режиме общее число частей задачи совпадает с количеством узлов, при одновременном выполнении нескольких задач некоторые задания в рамках одной и той же задачи назначатся одному и тому же узлу.
По умолчанию используется глобальный режим.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="includeEventTypes">
<list>
<!-- Эти события нужны для работы в режиме по задачам. -->
<util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FINISHED"/>
<util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FAILED"/>
<util:constant static-field="org.apache.ignite.events.EventType.EVT_JOB_MAPPED"/>
</list>
</property>
<property name="loadBalancingSpi">
<bean class="org.apache.ignite.spi.loadbalancing.roundrobin.RoundRobinLoadBalancingSpi">
<!-- Активируйте циклический режим по задачам. -->
<property name="perTask" value="true"/>
</bean>
</property>
</bean>
</beans>
RoundRobinLoadBalancingSpi spi = new RoundRobinLoadBalancingSpi();
spi.setPerTask(true);
IgniteConfiguration cfg = new IgniteConfiguration();
// Эти события нужны для работы в режиме по задачам.
cfg.setIncludeEventTypes(EventType.EVT_TASK_FINISHED, EventType.EVT_TASK_FAILED, EventType.EVT_JOB_MAPPED);
// Переопределите SPI балансировки нагрузки по умолчанию.
cfg.setLoadBalancingSpi(spi);
// Запустите узел.
Ignite ignite = Ignition.start(cfg);
Случайная и взвешенная балансировка нагрузки#
WeightedRandomLoadBalancingSpi выбирает случайный узел из списка доступных. При желании можно назначать вес для узлов, чтобы на узлы с бóльшим весом направлялось больше заданий. Вес всех узлов по умолчанию — 10.
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="loadBalancingSpi">
<bean class="org.apache.ignite.spi.loadbalancing.weightedrandom.WeightedRandomLoadBalancingSpi">
<property name="useWeights" value="true"/>
<property name="nodeWeight" value="10"/>
</bean>
</property>
</bean>
WeightedRandomLoadBalancingSpi spi = new WeightedRandomLoadBalancingSpi();
// Настройте SPI для использования алгоритма взвешенной балансировки нагрузки.
spi.setUseWeights(true);
// Установите вес для локального узла.
spi.setNodeWeight(10);
IgniteConfiguration cfg = new IgniteConfiguration();
// Переопределите SPI балансировки нагрузки по умолчанию.
cfg.setLoadBalancingSpi(spi);
// Запустите узел.
Ignite ignite = Ignition.start(cfg);
Перехват заданий (job stealing)#
Довольно часто кластеры развертываются на нескольких машинах. Некоторые из них могут быть более мощными или менее используемыми, чем другие. Включение JobStealingCollisionSpi поможет избежать очередей заданий в перегруженном узле: их перехватит малоиспользуемый узел.
С помощью JobStealingCollisionSpi происходит перехват задач из перегруженных в малоиспользуемые узлы. SPI особенно полезен при наличии заданий, которые быстро завершаются, пока другие задания находятся в очереди на перегруженных узлах. В этом случае ожидающие задания перенесутся с более медленного узла на более быстрый/малоиспользуемый узел.
JobStealingCollisionSpi наследует так называемую «позднюю» балансировку нагрузки. Она позволяет переназначать задачу с узла A на узел B после того, как выполнение задачи уже было запланировано на узле A.
Важно
Чтобы подключить перехват задач, настройте
JobStealingCollisionSpiв качестве SPI отказоустойчивости. Подробнее об этом написано в разделе «Отказоустойчивость».
Пример настройки JobStealingCollisionSpi:
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<!-- Включение требуемого SPI отказоустойчивости. -->
<property name="failoverSpi">
<bean class="org.apache.ignite.spi.failover.jobstealing.JobStealingFailoverSpi"/>
</property>
<!-- Включение `JobStealingCollisionSpi` для поздней балансировки нагрузки. -->
<property name="collisionSpi">
<bean class="org.apache.ignite.spi.collision.jobstealing.JobStealingCollisionSpi">
<property name="activeJobsThreshold" value="50"/>
<property name="waitJobsThreshold" value="0"/>
<property name="messageExpireTime" value="1000"/>
<property name="maximumStealingAttempts" value="10"/>
<property name="stealingEnabled" value="true"/>
<property name="stealingAttributes">
<map>
<entry key="node.segment" value="foobar"/>
</map>
</property>
</bean>
</property>
</bean>
JobStealingCollisionSpi spi = new JobStealingCollisionSpi();
// Настройте количество ожидающих заданий
// в очереди для перехвата.
spi.setWaitJobsThreshold(10);
// Настройте время истечения срока действия сообщения (в мс).
spi.setMessageExpireTime(1000);
// Настройте количество попыток перехвата.
spi.setMaximumStealingAttempts(10);
// Настройте количество активных заданий, которые можно выполнять
// одновременно. Это число должно совпадать с количеством
// потоков в пуле (по умолчанию — 100).
spi.setActiveJobsThreshold(50);
// Подключите перехват заданий.
spi.setStealingEnabled(true);
// Установите атрибут перехвата, чтобы перехватывать задания с/на узлы, в которых есть этот атрибут.
spi.setStealingAttributes(Collections.singletonMap("node.segment", "foobar"));
// Подключите `JobStealingFailoverSpi`.
JobStealingFailoverSpi failoverSpi = new JobStealingFailoverSpi();
IgniteConfiguration cfg = new IgniteConfiguration();
// Переопределите Collision SPI по умолчанию.
cfg.setCollisionSpi(spi);
cfg.setFailoverSpi(failoverSpi);