// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Load Balancing

:javaFile: {javaCodeDir}/LoadBalancing.java

Ignite automatically load balances jobs produced by a link:distributed-computing/map-reduce[compute task] as well as individual tasks submitted via the distributed computing API. Individual tasks submitted via `IgniteCompute.run(...)` and other compute methods are treated as tasks producing a single job.

////////////////////////////////////////////////////////////////////////////////

IgniteCompute.run(IgniteRunnable task)  -> produces one job

IgniteCompute.call(IgniteCallable task) -> produces one job

IgniteCompute.execute(ComputeTask) -> splits into multiple jobs

////////////////////////////////////////////////////////////////////////////////

By default, Ignite uses a round-robin algorithm (`RoundRobinLoadBalancingSpi`), which distributes jobs in sequential order across the nodes specified for the compute task.

[NOTE]
====
Load balancing does not apply to link:distributed-computing/collocated-computations[colocated computations].
====

The load balancing algorithm is controlled by the `IgniteConfiguration.loadBalancingSpi` property.

== Round-Robin Load Balancing

`RoundRobinLoadBalancingSpi` iterates through the available nodes in a round-robin fashion and picks the next sequential node. The available nodes are defined when you link:distributed-computing/distributed-computing#getting-the-compute-interface[get the compute instance] through which you execute your tasks.

Round-Robin load balancing supports two modes of operation: per-task and global.

When configured in per-task mode, the implementation picks a random node at the beginning of every task execution and then sequentially iterates through all the nodes in the topology starting from that node. For cases when the split size of a task is equal to the number of nodes, this mode guarantees that all nodes will participate in job execution.

[IMPORTANT]
====
The per-task mode requires that the following event types be enabled: `EVT_TASK_FAILED`, `EVT_TASK_FINISHED`, `EVT_JOB_MAPPED`.
====


When configured in global mode, a single sequential queue of nodes is maintained for all tasks and the next node in the queue is picked every time. In this mode (unlike in per-task mode), it is possible that even if the split size of a task is equal to the number of nodes, some jobs within the same task will be assigned to the same node whenever multiple tasks are executing concurrently.

The global mode is used by default.


[tabs]
--
tab:XML[]
[source,xml]
----
include::code-snippets/xml/round-robin-load-balancing.xml[tags=!discovery,indent=0]
----
tab:Java[]
[source,java]
----
include::{javaFile}[tag=load-balancing,indent=0]
----
tab:C#/.NET[unsupported]
tab:C++[unsupported]
--


== Random and Weighted Load Balancing
`WeightedRandomLoadBalancingSpi` picks a random node from the list of available nodes. You can also optionally assign weights to nodes, so that nodes with larger weights will end up getting proportionally more jobs routed to them. By default all nodes get a weight of 10.

[tabs]
--
tab:XML[]
[source,xml]
----
include::code-snippets/xml/weighted-load-balancing.xml[tags=ignite-config;!discovery,indent=0]
----
tab:Java[]
[source,java]
----
include::{javaFile}[tag=weighted,indent=0]
----
tab:C#/.NET[unsupported]
tab:C++[unsupported]
--

== Job Stealing

Quite often clusters are deployed across many computers some of which may be more powerful or under-utilized than others. Enabling `JobStealingCollisionSpi` helps avoid jobs being stuck at an over-utilized node, as they will be stolen by an under-utilized node.

`JobStealingCollisionSpi` supports job stealing from over-utilized nodes to under-utilized nodes. This SPI is especially useful if you have some jobs that complete quickly, while others are sitting in the waiting queue on over-utilized nodes. In such a case, the waiting jobs will be stolen from the slower node and moved to the fast/under-utilized node.

`JobStealingCollisionSpi` adopts a "late" load balancing technique, which allows reassigning a job from node A to node B after the job has been scheduled for execution on node A​.

[IMPORTANT]
====
If you want to enable job stealing, you have to configure `JobStealingFailoverSpi` as the failover SPI. See link:distributed-computing/fault-tolerance[Fault Tolerance] for details.
====


Here is an example of how to configure `JobStealingCollisionSpi`:

[tabs]
--
tab:XML[]
[source,xml]
----
include::code-snippets/xml/job-stealing.xml[tags=ignite-config;!discovery,indent=0]
----
tab:Java[]
[source,java]
----
include::{javaFile}[tag=job-stealing,indent=0]
----
tab:C#/.NET[unsupported]
tab:C++[unsupported]
--


