轮询调度算法
此算法为无状态的轮询算法:
(1) 无权重的轮询算法
假设有N台服务器,当前选中第i台
def servers = [0: s1, 1: s2, ... n-1: sn]
def n = servers.length
def i = n - 1
def j = i
def getNextServer(servers) {
do {
j = (j + 1) mod n
i = j
return servers[i]
} while (j != i)
return null
}
(2) 有权重的轮询算法
一组服务器 servers
每个服务器的权值 weights
当前选中的服务器 i
当前的权值 cw
服务器中最大的权值 max
服务器权值的最大公约数 gcd (greatest common divisor)
def servers = [0: s1, 1: s2, ... n-1: sn]
def weights = [0: w1, 1: w2, ... n-1: wn]
def i = -1
def n = servers.length
def gcd = gcd(weights)
def max = max(weights)
def cw = 0
def getNextServer(servers) {
while (true) {
i = (i + 1) mod n
if (i == 0) {
cw = cw - gcd
if (cw <= 0) {
cw = max
if (cw == 0) {
return null
}
}
}
if (servers[i].weight >= cw) {
return servers[i]
}
}
}
(3) Java测试代码
先看运行结果,5000次调度,权值高的轮询调度次数高
代码如下:
/**
* RoundRobin测试类
*/
public class RoundRobinTest {
public static void main(String[] args) {
// 初始化
List<Server> serverList = new ArrayList<Server>();
for (int i = 0; i < 10; i++) {
String ip = "192.168.1.1" + String.valueOf(i);
int weight = (int)(Math.random() * 100);
serverList.add(new Server(ip, weight));
}
RoundRobin rr = new RoundRobin<Server>(serverList);
// 模拟5000次轮询
for (int i = 0; i < 5000; i++) {
Server server = (Server) rr.next();
server.setCount(server.getCount() + 1);
}
// 打印结果
for (Server server : serverList) {
System.out.println(
"server: " + server.getIp() +
" weight: " + server.getWeight() +
" -- count: " + server.getCount());
}
}
}
/**
* 权重抽象类
*/
abstract class Weight {
public abstract int getWeight();
}
/**
* 服务器信息
*/
class Server extends Weight {
private String ip;
private int weight; // 权重
private int count = 0; // 调度次数
public Server(String ip, int weight) {
this.ip = ip;
this.weight = weight;
}
public String getIp() {
return ip;
}
public int getWeight() {
return weight;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
/**
* 算法实现
*/
class RoundRobin<T extends Weight> {
private List<T> list;
private int i = -1, n, cw, gcd, max;
public RoundRobin(List<T> list) {
this.list = list;
n = list.size();
gcd = getGcdOfWeight(list);
max = getMaxWeight(list);
}
public T next() {
while (true) {
i = (i + 1) % n;
if (i == 0) {
cw = cw - gcd;
if (cw <= 0) {
cw = max;
if (cw == 0) {
return null;
}
}
}
T t = list.get(i);
if (t.getWeight() >= cw) {
return t;
}
}
}
/**
* 得到最大公约数
* @param list
* @return
*/
private int getGcdOfWeight(List<T> list) {
return 1;
}
/**
* 得到最大的权值
* @param list
* @return
*/
private int getMaxWeight(List<T> list) {
int w = list.get(0).getWeight();
for (int i = 1; i < list.size(); i++) {
T t = list.get(i);
if (t.getWeight() > w) {
w = t.getWeight();
}
}
return w;
}
}