常见的负载均衡策略
轮询(Round Robin)
轮询的实现方式比较简单,就是将请求以此分发到后端服务器中,将所有的请求均匀分配,均匀分配的坏处是通常后台服务器性能有差异,有时候希望性能较好的服务器可以多承担些请求,该策略无法满足需求。这个不适合对长连接和命中率有要求的场景。
加强轮询(Weighted Round Robin)
这种策略是对轮询策略的优化,对每个后端服务器设置一个权重值,根据权重值决定请求的分配比例,这种做法解决了轮询策略的不足,但是该权限值需要手动配置,没有办法自动动态调节,同样不适合对长连接和命中率有要求的场景。
hash算法
通过ip url等信息计算hash值,然后对服务器的数量取模,相同的请求会请求到同一个后端服务器中。该算法无法解决热点请求,会把某个时间段的热点请求路由到某个单机上,造成雪崩效应,同时在扩中和节点宕机时发生命中率急剧降低的问题(hash算法导致),该策略适合维护长连接和提高命中率。
随机Random
根据随机算法,将请求随机分配到后端服务器中,请求的均匀请求依赖于随机算法,该实现方式较为简单,常常可以配合处理一些极端的请求,例如热点请求情况。不适合对命中率有要求的场景。
一致性hash算法
对hash 算法的优化,可以有效的解决宕机和扩充造成的命中率急剧降低的问题。
最小连接数 Least Connection
通过活动来估计后端服务器的负载,把请求分配给活动连接数最小的后端服务器,算法比较智能,但是需要额外的资源维护后端服务器的连接列表。
加权最小连接数 Weighted Least Connection
对Least Connection策略的优化,通过加权的方式优化Least Connection的性能,对性能较好的后端服务器设置较高的权重,承担更多的链接负载。
最短响应时间 Least Response Time
该策略的意思就是将请求分配给平均响应时间最短的后端服务器,平均时间可以通过ping或者正常的响应时间来获取 。
可以总结为,轮巡、随机、权重、并发量
后面会逐一对各个常见的负载均衡策略的实现做介绍。
自我总结
在 Java 开发中,负载均衡是一种将工作负载分布到多个计算资源(如服务器、处理器等)上的技术,以提高系统的性能、可用性和可扩展性。以下是几种常见的 Java 负载均衡策略及示例说明。
1. 轮询策略(Round Robin)
原理
轮询策略是最简单的负载均衡策略之一。它按照顺序依次将请求分配到可用的服务器列表中的每一台服务器,当所有服务器都被分配过一次后,再从头开始循环。
示例代码
import java.util.ArrayList;
import java.util.List;
// 模拟服务器列表
class Server {
private String name;
public Server(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 轮询负载均衡器
class RoundRobinLoadBalancer {
private List<Server> servers;
private int currentIndex = 0;
public RoundRobinLoadBalancer(List<Server> servers) {
this.servers = servers;
}
public Server getNextServer() {
Server server = servers.get(currentIndex);
currentIndex = (currentIndex + 1) % servers.size();
return server;
}
}
public class RoundRobinExample {
public static void main(String[] args) {
List<Server> servers = new ArrayList<>();
servers.add(new Server("Server1"));
servers.add(new Server("Server2"));
servers.add(new Server("Server3"));
RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(servers);
// 模拟 5 次请求
for (int i = 0; i < 5; i++) {
Server server = loadBalancer.getNextServer();
System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
}
}
}
代码解释
在上述代码中,RoundRobinLoadBalancer
类实现了轮询负载均衡策略。getNextServer
方法会依次返回服务器列表中的服务器,当到达列表末尾时,会重新从列表头部开始。
2. 随机策略(Random)
原理
随机策略会随机选择一台可用的服务器来处理请求。这种策略简单且易于实现,但可能会导致服务器负载不均衡。
示例代码
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
// 模拟服务器列表
class Server {
private String name;
public Server(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 随机负载均衡器
class RandomLoadBalancer {
private List<Server> servers;
private Random random = new Random();
public RandomLoadBalancer(List<Server> servers) {
this.servers = servers;
}
public Server getNextServer() {
int index = random.nextInt(servers.size());
return servers.get(index);
}
}
public class RandomExample {
public static void main(String[] args) {
List<Server> servers = new ArrayList<>();
servers.add(new Server("Server1"));
servers.add(new Server("Server2"));
servers.add(new Server("Server3"));
RandomLoadBalancer loadBalancer = new RandomLoadBalancer(servers);
// 模拟 5 次请求
for (int i = 0; i < 5; i++) {
Server server = loadBalancer.getNextServer();
System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
}
}
}
代码解释
RandomLoadBalancer
类实现了随机负载均衡策略。getNextServer
方法会随机选择一个服务器索引,并返回对应的服务器。
3. 加权轮询策略(Weighted Round Robin)
原理
加权轮询策略是轮询策略的改进版。为每台服务器分配一个权重,权重越高的服务器被分配到请求的概率越大。例如,服务器 A 的权重为 3,服务器 B 的权重为 1,那么在 4 次请求中,服务器 A 可能会被分配到 3 次,服务器 B 会被分配到 1 次。
示例代码
import java.util.ArrayList;
import java.util.List;
// 模拟服务器列表
class Server {
private String name;
private int weight;
public Server(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public int getWeight() {
return weight;
}
}
// 加权轮询负载均衡器
class WeightedRoundRobinLoadBalancer {
private List<Server> servers;
private int currentIndex = 0;
private int currentWeight = 0;
private int gcd; // 最大公约数
private int maxWeight; // 最大权重
public WeightedRoundRobinLoadBalancer(List<Server> servers) {
this.servers = servers;
this.gcd = getGCD(servers);
this.maxWeight = getMaxWeight(servers);
}
private int getGCD(List<Server> servers) {
int gcd = servers.get(0).getWeight();
for (int i = 1; i < servers.size(); i++) {
gcd = gcd(gcd, servers.get(i).getWeight());
}
return gcd;
}
private int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
private int getMaxWeight(List<Server> servers) {
int max = servers.get(0).getWeight();
for (int i = 1; i < servers.size(); i++) {
if (servers.get(i).getWeight() > max) {
max = servers.get(i).getWeight();
}
}
return max;
}
public Server getNextServer() {
while (true) {
currentIndex = (currentIndex + 1) % servers.size();
if (currentIndex == 0) {
currentWeight = currentWeight - gcd;
if (currentWeight <= 0) {
currentWeight = maxWeight;
if (currentWeight == 0) {
return null;
}
}
}
Server server = servers.get(currentIndex);
if (server.getWeight() >= currentWeight) {
return server;
}
}
}
}
public class WeightedRoundRobinExample {
public static void main(String[] args) {
List<Server> servers = new ArrayList<>();
servers.add(new Server("Server1", 3));
servers.add(new Server("Server2", 1));
servers.add(new Server("Server3", 2));
WeightedRoundRobinLoadBalancer loadBalancer = new WeightedRoundRobinLoadBalancer(servers);
// 模拟 6 次请求
for (int i = 0; i < 6; i++) {
Server server = loadBalancer.getNextServer();
System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
}
}
}
代码解释
WeightedRoundRobinLoadBalancer
类实现了加权轮询负载均衡策略。通过计算服务器权重的最大公约数和最大权重,按照一定规则依次选择服务器。
4. 最少连接策略(Least Connections)
原理
最少连接策略会选择当前连接数最少的服务器来处理请求。这种策略可以使服务器的负载更加均衡,因为它会优先将请求分配给负载较轻的服务器。
示例代码(简单模拟)
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
// 模拟服务器列表
class Server {
private String name;
private int connections;
public Server(String name) {
this.name = name;
this.connections = 0;
}
public String getName() {
return name;
}
public int getConnections() {
return connections;
}
public void incrementConnections() {
connections++;
}
public void decrementConnections() {
connections--;
}
}
// 最少连接负载均衡器
class LeastConnectionsLoadBalancer {
private List<Server> servers;
public LeastConnectionsLoadBalancer(List<Server> servers) {
this.servers = servers;
}
public Server getNextServer() {
return servers.stream()
.min(Comparator.comparingInt(Server::getConnections))
.orElse(null);
}
}
public class LeastConnectionsExample {
public static void main(String[] args) {
List<Server> servers = new ArrayList<>();
servers.add(new Server("Server1"));
servers.add(new Server("Server2"));
servers.add(new Server("Server3"));
LeastConnectionsLoadBalancer loadBalancer = new LeastConnectionsLoadBalancer(servers);
// 模拟 5 次请求
for (int i = 0; i < 5; i++) {
Server server = loadBalancer.getNextServer();
server.incrementConnections();
System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
}
}
}
代码解释
LeastConnectionsLoadBalancer
类实现了最少连接负载均衡策略。getNextServer
方法会选择当前连接数最少的服务器。每次请求分配后,会增加对应服务器的连接数。
这些负载均衡策略各有优缺点,在实际应用中,需要根据具体的业务场景和服务器配置选择合适的策略。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2017-04-24 java面试题总结
2017-04-24 Spring 使用注解方式进行事务管理
2017-04-24 高级程序员的面试题整理
2017-04-24 Web性能优化
2017-04-24 设计模式-单例模式7种写法
2017-04-24 线程池的原理及实现