1.普通轮询算法
轮询(Round Robin,RR)是依次将用户的访问请求,按循环顺序分配到web服务节点上,从1开始到最后一台服务器节点结束,然后再开始新一轮的循环。这种算法简单,但是没有考虑到每台节点服务器的具体性能,请求分发往往不均衡。
代码实现:
/** * 普通轮询算法 */public class RoundRobin { private static Integer index = 0; private static List<String> nodes = new ArrayList<>(); // 准备模拟数据 static { nodes.add("192.168.1.101"); nodes.add("192.168.1.103"); nodes.add("192.168.1.102"); System.out.println("普通轮询算法的所有节点:"+nodes);//打印所有节点 } // 关键代码 public String selectNode(){ String ip = null; synchronized (index){ // 下标复位 if(index>=nodes.size()) index = 0; ip = nodes.get(index); index++; } return ip; } // 并发测试:两个线程循环获取节点 public static void main(String[] args) { new Thread(() -> { RoundRobin roundRobin1 = new RoundRobin(); for (int i=1;i<=5;i++){ String serverIp = roundRobin1.selectNode(); System.out.println(Thread.currentThread().getName()+"==第"+i+"次获取节点:"+serverIp); } }).start(); RoundRobin roundRobin2 = new RoundRobin(); for (int i=1;i<=nodes.size();i++){ String serverIp = roundRobin2.selectNode(); System.out.println(Thread.currentThread().getName()+"==第"+i+"次获取节点:"+serverIp); } } }
执行结果:不同线程访问,结果依旧是按顺序循环分配节点
普通轮询算法的所有节点:[192.168.1.101, 192.168.1.103, 192.168.1.102]
main==第1次获取节点:192.168.1.101
Thread-0==第1次获取节点:192.168.1.103
Thread-0==第2次获取节点:192.168.1.102
Thread-0==第3次获取节点:192.168.1.101
Thread-0==第4次获取节点:192.168.1.103
Thread-0==第5次获取节点:192.168.1.102
main==第2次获取节点:192.168.1.101
main==第3次获取节点:192.168.1.103
2.加权轮询算法
加权轮询(Weighted Round Robin,WRR)是根据设定的权重值来分配访问请求,权重值越大的,被分到的请求数也就越多。一般根据每台节点服务器的具体性能来分配权重。
2.1.实现方式一
将需要轮询的所有节点 按权重数 循环生成一个List 集合,然后就跟普通轮询算法一样,来一个、分配一个、进1位。
例如:
所有节点信息:{ {“192.168.1.100“,5},{“192.168.1.101“,1},{“192.168.1.102“,3}}
那么生成的List 集合为:
{“192.168.1.100“,
“192.168.1.100“,
“192.168.1.100“,
“192.168.1.100“,
“192.168.1.100“,
“192.168.1.101“,
“192.168.1.102“,
“192.168.1.102“,
“192.168.1.102“}
后面就是普通轮询算法的逻辑
代码实现:
类似于二维数组 降维成 一维数组,然后使用普通轮询
/** * 简单版的加权轮询 */public class WeightedRoundRobinSimple { private static Integer index = 0; private static Map<String,Integer> mapNodes = new HashMap<>(); // 准备模拟数据 static { mapNodes.put("192.168.1.101",1); mapNodes.put("192.168.1.102",3); mapNodes.put("192.168.1.103",2); /* -- 以下代码只为了方便查看所有节点,删除不影响 -- S */ List<String> nodes = new ArrayList<>(); Iterator<Map.Entry<String, Integer>> iterator = mapNodes.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> entry = iterator.next(); String key = entry.ge