加权轮询算法:不同的后端服务器,在机器的配置和当前系统的负载方面,可能并不相同。因此,它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请求;给配置低、负载高的机器分配较低的权重,降低系统负载。加权轮询算法能很好地处理这一问题,并将请求顺序地按照权重分配到后端服务器。

一、算法描述

假设有 N 台服务器 S = {S0, S1, S2, …, Sn},默认权重为 W = {W0, W1, W2, …, Wn},服务器列表为 serverList,算法可以描述为:

1、初始化 serverList,将 W0 个 S0 加入至serverList,将 W1 个 S1 加入至serverList,依据此规则,将所有的服务器加入至 serverList 中;

2、从 serverList 的从 S0 开始依序调度;

3、若所有服务器都已被调度过,则从头重新开始,循环调度。

假定我们现在有如下四台服务器:

服务器地址权重192.168.1.11

192.168.1.22

192.168.1.33

192.168.1.44

初始化服务列表后, serverList 如下:

服务器地址序号192.168.1.11

192.168.1.22

192.168.1.23

192.168.1.34

192.168.1.35

192.168.1.36

192.168.1.47

192.168.1.48

192.168.1.49

192.168.1.410

通过在服务器列表中增加相应权重个数的服务器,加权轮训算法实现加权效果,每个服务器会依序被轮训到。

二、java代码实现

package com.test.mvp.schedulealgothrim;

import com.google.common.collect.SortedMultiset;

import com.google.common.collect.TreeMultiset;

import org.springframework.util.CollectionUtils;

import java.io.Serializable;

import java.util.ArrayList;

import java.util.Map;

import java.util.Set;

import java.util.TreeMap;

import java.util.concurrent.atomic.AtomicInteger;

class Server implements Serializable {

private static final long serialVersionUID = 7246747589293111189L;

private String server;

private Integer weight;

private String description;

public Server(String server, String description, Integer weight) {

this.server = server;

this.description = description;

this.weight = weight;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public String getServer() {

return server;

}

public void setServer(String server) {

this.server = server;

}

public Integer getWeight() {

return weight;

}

public void setWeight(Integer weight) {

this.weight = weight;

}

}

class ServerManager {

public static Map serverMap = new TreeMap<>();

static {

serverMap.put("192.168.1.1", new Server("192.168.1.1", "第1台server", 1));

serverMap.put("192.168.1.2", new Server("192.168.1.2", "第2台server", 2));

serverMap.put("192.168.1.3", new Server("192.168.1.3", "第3台server", 3));

serverMap.put("192.168.1.4", new Server("192.168.1.4", "第4台server", 4));

}

}

class WeightRoundRobin {

private static AtomicInteger indexAtomic = new AtomicInteger(0);

private static ArrayList middleServerList;

public static void computeMiddleServerList() {

ArrayList serverList = new ArrayList<>();

Set serverSet = ServerManager.serverMap.keySet();

for (String server : serverSet) {

Integer weight = ServerManager.serverMap.get(server).getWeight();

for (int i = 0; i < weight; i++) {

serverList.add(server);

}

}

middleServerList = serverList;

}

public static String getServer() {

if (CollectionUtils.isEmpty(middleServerList)) {

computeMiddleServerList();

System.out.println("compute Middle Server List");

}

if (indexAtomic.get() >= middleServerList.size()) {

indexAtomic.set(0);

}

return middleServerList.get(indexAtomic.getAndIncrement());

}

}

public class WeightRoundRobinTest {

public static void main(String[] args) {

SortedMultiset serverSet = TreeMultiset.create();

for (int i = 0; i < 100; i++) {

String server = WeightRoundRobin.getServer();

Server curServer = ServerManager.serverMap.get(server);

System.out.println(server + ", " + curServer.getDescription() + ", weight=" + curServer.getWeight());

serverSet.add(server, 1);

}

ServerManager.serverMap.forEach((key, value)->{

System.out.println(key + ", count:" + serverSet.count(key));

});

}

}

运行结果如下所示:

compute Middle Server List

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, 第1台server, weight=1

192.168.1.2, 第2台server, weight=2

192.168.1.2, 第2台server, weight=2

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.3, 第3台server, weight=3

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.4, 第4台server, weight=4

192.168.1.1, count:10

192.168.1.2, count:20

192.168.1.3, count:30

192.168.1.4, count:40

说明:

1、使用 AtomicInteger 进行轮询索引的增减,保证并发的安全性。

2、在多线程的情况下,若线程A修改 ServerManager.serverMap 的值,则线程B无法即时拿到线程A修改后的值,可能会导致请求错误,需要调用方进行容错处理。

3、从宏观的角度讲,权重高的服务器被访问的次数高一些,近似均衡;微观的角度讲,权重高的服务器会被连续访问到,局部没有那么均衡。

本文地址:https://blog.csdn.net/chinawangfei/article/details/109593274

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐