负载均衡算法是分布式系统中用于将请求均匀分配到多个服务器上的重要技术,以下是几种常见的负载均衡算法及其Java代码实现:
轮询法(Round Robin)


简介
轮询法按顺序将每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。
Java代码实现
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class TestRoundRobin {
// 定义map, key-ip, value-weight
static Map<String, Integer> ipMap = new HashMap<>();
static {
ipMap.put("192.168.13.1", 1);
ipMap.put("192.168.13.2", 1);
ipMap.put("192.168.13.3", 1);
}
private static Integer pos = 0;
public String RoundRobin() {
Map<String, Integer> ipServerMap = new ConcurrentHashMap<>();
ipServerMap.putAll(ipMap);
Set<String> ipSet = ipServerMap.keySet();
ArrayList<String> ipList = new ArrayList<>(ipSet);
synchronized (pos) {
if (pos >= ipSet.size()) {
pos = 0;
}
String serverName = ipList.get(pos);
pos++;
return serverName;
}
}
public static void main(String[] args) {
TestRoundRobin testRoundRobin = new TestRoundRobin();
for (int i = 0; i < 10; i++) {
String serverIp = testRoundRobin.RoundRobin();
System.out.println(serverIp);
}
}
}
加权轮询法(Weighted Round Robin)
简介
加权轮询法在轮询的基础上,根据服务器的权重比例来分配请求,权重越高的服务器会接收更多的请求。
Java代码实现

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class TestWeightRobin {
// map, key-ip, value-weight
static Map<String, Integer> ipMap = new HashMap<>();
static {
ipMap.put("192.168.13.1", 1);
ipMap.put("192.168.13.2", 2);
ipMap.put("192.168.13.3", 4);
}
private static Integer pos = 0;
private static int currentWeight = 0;
private static int gcdWeight = 0;
public String WeightRobin() {
Map<String, Integer> ipServerMap = new ConcurrentHashMap<>();
ipServerMap.putAll(ipMap);
Set<String> ipSet = ipServerMap.keySet();
Iterator<String> ipIterator = ipSet.iterator();
ArrayList<String> ipList = new ArrayList<>();
while (ipIterator.hasNext()) {
String serverName = ipIterator.next();
Integer weight = ipServerMap.get(serverName);
for (int i = 0; i < weight; i++) {
ipList.add(serverName);
}
}
synchronized (this) {
if (currentWeight >= gcdWeight) {
currentWeight -= gcdWeight;
if (currentWeight < 0) {
currentWeight += gcdWeight;
}
}
String serverName = ipList.get(currentWeight);
currentWeight++;
return serverName;
}
}
public static void main(String[] args) {
TestWeightRobin testWeightRobin = new TestWeightRobin();
for (int i = 0; i < 10; i++) {
String serverIp = testWeightRobin.WeightRobin();
System.out.println(serverIp);
}
}
}
随机法(Random)
简介
随机法通过系统随机函数,从服务器列表中随机选取一台服务器进行访问,随着调用量的增加,其实际效果越来越接近于平均分配流量到每一台后端服务器。
Java代码实现
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class TestRandom {
// map, key-ip, value-weight
static Map<String, Integer> ipMap = new HashMap<>();
static {
ipMap.put("192.168.13.1", 1);
ipMap.put("192.168.13.2", 2);
ipMap.put("192.168.13.3", 4);
}
public String Random() {
Map<String, Integer> ipServerMap = new ConcurrentHashMap<>();
ipServerMap.putAll(ipMap);
Set<String> ipSet = ipServerMap.keySet();
ArrayList<String> ipList = new ArrayList<>(ipSet);
Random random = new Random();
int randomPos = random.nextInt(ipList.size());
return ipList.get(randomPos);
}
public static void main(String[] args) {
TestRandom testRandom = new TestRandom();
for (int i = 0; i < 10; i++) {
String serverIp = testRandom.Random();
System.out.println(serverIp);
}
}
}
IP哈希法(IP_Hash)
简介
IP哈希法通过获取客户端访问的IP地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是要访问的服务器序号,这种方法可以确保来自同一个IP地址的请求会被分配到同一台服务器上。
Java代码实现
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.math.BigInteger;
public class TestIpHash {
// map, key-ip, value-weight
static Map<String, Integer> ipMap = new HashMap<>();
static {
ipMap.put("192.168.13.1", 1);
ipMap.put("192.168.13.2", 2);
ipMap.put("192.168.13.3", 4);
}
public String IpHash() throws NoSuchAlgorithmException {
Map<String, Integer> ipServerMap = new ConcurrentHashMap<>();
ipServerMap.putAll(ipMap);
Set<String> ipSet = ipServerMap.keySet();
ArrayList<String> ipList = new ArrayList<>(ipSet);
String clientIp = "192.168.13.4"; // 假设客户端IP地址为192.168.13.4
int serverIndex = getServerIndex(clientIp, ipList);
return ipList.get(serverIndex);
}
private int getServerIndex(String clientIp, List<String> serverList) throws NoSuchAlgorithmException {
byte[] digest = MessageDigest.getInstance("MD5").digest(clientIp.getBytes());
BigInteger hashValue = new BigInteger(1, digest);
return Math.abs(hashValue.mod(new BigInteger(serverList.size())).intValue();
}
public static void main(String[] args) throws NoSuchAlgorithmException {
TestIpHash testIpHash = new TestIpHash();
for (int i = 0; i < 10; i++) {
String serverIp = testIpHash.IpHash();
System.out.println(serverIp);
}
}
}
最小连接数法(Least Connections)
简介
最小连接数法优先选择当前活动连接数最少的服务器来处理新的连接请求,该方法需要实时监控各服务器的连接数。
Java代码实现
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class TestLeastConnections {
// map, key-ip, value-connection count and weight
static Map<String, AtomicInteger> connectionCountMap = new ConcurrentHashMap<>();
static {
connectionCountMap.put("192.168.13.1", new AtomicInteger(0));
connectionCountMap.put("192.168.13.2", new AtomicInteger(0));
connectionCountMap.put("192.168.13.3", new AtomicInteger(0));
}
public String LeastConnections() {
String selectedServer = null;
int minConnections = Integer.MAX_VALUE;
synchronized (connectionCountMap) {
for (Map.Entry<String, AtomicInteger> entry : connectionCountMap.entrySet()) {
int currentConnections = entry.getValue().get();
if (currentConnections < minConnections) {
minConnections = currentConnections;
selectedServer = entry.getKey();
}
}
if (selectedServer != null) {
connectionCountMap.get(selectedServer).incrementAndGet(); // Simulate a new connection being added to the selected server
}
}
return selectedServer;
}
public static void main(String[] args) {
TestLeastConnections testLeastConnections = new TestLeastConnections();
for (int i = 0; i < 10; i++) {
String serverIp = testLeastConnections.LeastConnections();
System.out.println(serverIp);
}
}
}
相关问题与解答栏目
问题1: 为什么在轮询法中需要使用synchronized关键字?解答: 在轮询法中,为了保证多个线程同时访问时,pos变量的修改不会导致数据不一致或并发问题,需要使用synchronized关键字对其进行同步控制,这样可以确保在同一时刻只有一个线程能够修改pos的值,从而保证服务器选择的顺序性。问题2: 加权轮询法中的gcdWeight是如何计算的?解答:gcdWeight是所有服务器权重的最大公约数,用于确定轮询的步长,它的计算可以通过遍历所有权重并使用辗转相除法求得最大公约数来实现,具体实现可以参考以下代码片段:“java private static int findGCD(int a, int b) { return b == 0 ? a : findGCD(b, a % b); } public static void calculateGCD() { int totalWeight = 0; for (int weight : ipMap.values()) { totalWeight += weight; } for (int weight : ipMap.values()) { gcdWeight = findGCD(gcdWeight, weight); } }`在初始化阶段调用calculateGCD()方法即可计算出gcdWeight`。
以上就是关于“负载均衡算法代码”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!














