Java Load Balancing Algorithms: Round Robin, Random, Source‑IP Hash, Weighted Round Robin, Weighted Random, and Least Connections
This article explains the concept of load balancing and provides Java implementations of several common algorithms—including Round Robin, Random, Source‑IP Hash, Weighted Round Robin, Weighted Random, and a discussion of Least Connections—highlighting their principles, advantages, drawbacks, and concurrency considerations.
Load balancing distributes incoming requests across multiple servers to improve bandwidth, throughput, flexibility, and availability; it can be described as allocating external requests evenly among a symmetric server pool.
The article first defines load balancing and then presents a Java class IpMap that simulates a list of server IPs with associated weights.
import java.util.HashMap;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
public class IpMap {
// Key: IP, Value: weight
public static HashMap
serverWeightMap = new HashMap
();
static {
serverWeightMap.put("192.168.1.100", 1);
serverWeightMap.put("192.168.1.101", 1);
serverWeightMap.put("192.168.1.102", 4);
serverWeightMap.put("192.168.1.103", 1);
serverWeightMap.put("192.168.1.104", 1);
serverWeightMap.put("192.168.1.105", 3);
serverWeightMap.put("192.168.1.106", 1);
serverWeightMap.put("192.168.1.107", 2);
serverWeightMap.put("192.168.1.108", 1);
serverWeightMap.put("192.168.1.109", 1);
serverWeightMap.put("192.168.1.110", 1);
}
}Round Robin cycles through the server list sequentially, requiring no state tracking beyond a position counter; however, concurrency demands a synchronized block to protect the counter.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
class RoundRobin {
private static Integer pos = 0;
public static String getServer() {
Map
serverMap = new HashMap
();
serverMap.putAll(IpMap.serverWeightMap);
Set keySet = serverMap.keySet();
ArrayList keyList = new ArrayList();
keyList.addAll(keySet);
String server = null;
synchronized (pos) {
if (pos > keySet.size() - 1) pos = 0;
server = (String) keyList.get(pos);
pos++;
}
return server;
}
}Random selects a server by generating a random index within the server list, offering probabilistic distribution that approximates round robin as request volume grows.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
class Random {
public static String getServer() {
Map
serverMap = new HashMap
();
serverMap.putAll(IpMap.serverWeightMap);
Set keySet = serverMap.keySet();
ArrayList keyList = new ArrayList();
keyList.addAll(keySet);
java.util.Random random = new java.util.Random();
int randomPos = random.nextInt(keyList.size());
return (String) keyList.get(randomPos);
}
}Source‑IP Hash hashes the client’s IP address and uses the modulus of the server list size to pick a server, ensuring the same client IP consistently maps to the same backend as long as the server pool remains unchanged.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
class Hash {
public static String getServer() {
Map
serverMap = new HashMap
();
serverMap.putAll(IpMap.serverWeightMap);
Set keySet = serverMap.keySet();
ArrayList keyList = new ArrayList();
keyList.addAll(keySet);
String remoteIp = "127.0.0.1"; // example client IP
int hashCode = remoteIp.hashCode();
int serverPos = hashCode % keyList.size();
return (String) keyList.get(serverPos);
}
}Weighted Round Robin expands the server list by replicating each server address according to its weight, then applies the round‑robin counter on this expanded list, giving higher‑weight servers more selections.
import java.util.*;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
class WeightRoundRobin {
private static Integer pos;
public static String getServer() {
Map
serverMap = new HashMap
();
serverMap.putAll(IpMap.serverWeightMap);
Set keySet = serverMap.keySet();
Iterator iterator = keySet.iterator();
List serverList = new ArrayList();
while (iterator.hasNext()) {
String server = (String) iterator.next();
int weight = serverMap.get(server);
for (int i = 0; i < weight; i++) {
serverList.add(server);
}
}
String server = null;
synchronized (pos) {
if (pos > serverList.size() - 1) pos = 0;
server = (String) serverList.get(pos);
pos++;
}
return server;
}
}Weighted Random builds the same weighted server list as above but selects an entry using a random index, combining the concepts of weighted distribution and randomness.
import java.util.*;
/**
* @author [email protected]
* @date 二月 07, 2017
*/
class WeightRandom {
public static String getServer() {
Map
serverMap = new HashMap
();
serverMap.putAll(IpMap.serverWeightMap);
Set keySet = serverMap.keySet();
Iterator iterator = keySet.iterator();
List serverList = new ArrayList();
while (iterator.hasNext()) {
String server = (String) iterator.next();
int weight = serverMap.get(server);
for (int i = 0; i < weight; i++) {
serverList.add(server);
}
}
java.util.Random random = new java.util.Random();
int randomPos = random.nextInt(serverList.size());
return (String) serverList.get(randomPos);
}
}The article also mentions Least Connections , an adaptive method that selects the server with the fewest active connections, noting that request‑count balancing does not always reflect true load and that connection‑aware routing can improve resource utilization, though its implementation is more complex and is not detailed here.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.