负载均衡算法--轮询法(Round Robin)
在分布式系统中,为了实现系统的高性能、高并发、高可用,在构架中都会进行负载均衡设计,它是分布式系统的核心和中枢,负载均衡的好坏直接影响着整个系统的性能。负载均衡分为软件均衡和硬件均衡两类,比如apache、nginx、dubbo 等属于软件负载均衡,F5属于硬件负载均衡,当然他们都会使用到负载均衡算法。常见的负载均衡算法包含:1、轮询法(Round Robin)2、加权轮询法(Weight ...
在分布式系统中,为了实现系统的高性能、高并发、高可用,在构架中都会进行负载均衡设计,它是分布式系统的核心和中枢,负载均衡的好坏直接影响着整个系统的性能。负载均衡分为软件均衡和硬件均衡两类,比如apache、nginx、dubbo 等属于软件负载均衡,F5属于硬件负载均衡,当然他们都会使用到负载均衡算法。
常见的负载均衡算法包含:
1、轮询法(Round Robin)
2、加权轮询法(Weight Round Robin)
3、随机法(Random)
4、加权随机法(Weight Random)
5、平滑加权轮询法(Smooth Weight Round Robin)
6、源地址哈希法(Hash)
7、最小连接数法(Least Connections)
接下来的博客中会一一介绍如上几种算法,本文介绍轮询法。
轮询法是将请求按顺序轮流地分配到服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
算法描述
假设有 N 台服务器 S = {S0, S1, S2, …, Sn},算法可以描述为:
1、从 S0 开始依次调度 S1, S2, …, Sn;
2、若所有服务器都已被调度过,则从头开始调度;
假定我们现在有如下四台服务器:
服务器地址 | 权重 |
---|---|
192.168.1.1 | 1 |
192.168.1.2 | 2 |
192.168.1.3 | 3 |
192.168.1.4 | 4 |
轮训算法调度如下:
服务器地址 | 序号 |
---|---|
192.168.1.1 | 1 |
192.168.1.2 | 2 |
192.168.1.3 | 3 |
192.168.1.4 | 4 |
192.168.1.1 | 5 |
192.168.1.2 | 6 |
192.168.1.3 | 7 |
192.168.1.4 | 8 |
轮训算法与服务器权重没有关系,每个服务器有序的会被轮训到。
代码实现
1、服务器管理类
package org.learn.loadbalance;
import java.util.Map;
import java.util.TreeMap;
/**
* @author zhibo
* @date 2019/5/16 16:25
*/
public class ServerManager {
public static Map<String, Integer> serverMap = new TreeMap<>();
static {
serverMap.put("192.168.1.1", 1);
serverMap.put("192.168.1.2", 2);
serverMap.put("192.168.1.3", 3);
serverMap.put("192.168.1.4", 4);
}
}
2、轮询类
package org.learn.loadbalance;
import java.util.ArrayList;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author zhibo
* @date 2019/5/16 16:28
*/
public class RoundRobin {
private static AtomicInteger indexAtomic = new AtomicInteger(0);
public static String getServer() {
Set<String> serverSet = ServerManager.serverMap.keySet();
ArrayList<String> serverList = new ArrayList<>(serverSet);
if (indexAtomic.get() >= serverList.size()) {
indexAtomic.set(0);
}
String server = serverList.get(indexAtomic.getAndIncrement());
return server;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
String server = getServer();
System.out.println(server);
}
}
}
1、使用 AtomicInteger 进行轮询索引的增减,保证并发的安全性。
2、在多线程的情况下, 线程A修改 ServerManager.serverMap 的值,线程B无法即时拿到线程A修改后的值,因此可能会产生请求错误,需要调用端进行容错处理。
执行 main 方法输出结果如下:
文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)