假设有一组服务器(Server)S = {S0, S1, ..., Sn-1}
,W(Si)
表示服务器Si
的权值(Weight),C(Si)
表示服务器Si
的当前连接数(Connection)。所有服务器当前连接数的总和为:CSUM = ΣC(Si) (i=0, 1, .. , n-1)
当前的新连接请求会被发送服务器Sm
,当且仅当服务器Sm
满足以下条件:(C(Sm) / CSUM)/ W(Sm) = min { (C(Si) / CSUM) / W(Si)} (i=0, 1, . , n-1)
其中W(Si)
不为零
因为CSUM在这一轮查找中是个常数,所以判断条件可以简化为:C(Sm) / W(Sm) = min { C(Si) / W(Si)} (i=0, 1, . , n-1)
其中W(Si)
不为零
因为除法所需的CPU周期比乘法多,且在Linux内核中不允许浮点除法,服务器的权值都大于零,所以判断条件C(Sm) / W(Sm) > C(Si) / W(Si)
可以进一步优化为C(Sm)*W(Si) > C(Si)* W(Sm)
。
同时保证服务器的权值为零时,服务器不被调度。所以,算法只要执行以下流程:
伪代码:
for (m = 0; m < n; m++) {
if (W(Sm) > 0) {
for (i = m+1; i < n; i++) {
if (C(Sm)*W(Si) > C(Si)*W(Sm))
m = i;
}
return Sm;
}
}
return NULL;
go语言的实现如下:
// WeightedLeastConnectionScheduling 加权最小连接调度算法
// n 服务器的数量
// W 服务器的权重
// C 服务器现有连接的数量
// 返回值:选定的服务器下标
func WeightedLeastConnectionScheduling(n int, W []int, C []int) *int {
for m := 0; m < n; m++ {
if W[m] > 0 {
for i := m + 1; i < n; i++ {
if C[m]*W[i] > C[i]*W[m] {
m = i
}
}
return &m
}
}
return nil
}
java 语言实现如下:
/**
* 加权最小连接调度算法
*
* @param n 服务器的数量
* @param W 服务器的权重
* @param C 服务器现存连接的数量
* @return 选定的服务器下标
*/
public Integer WeightedLeastConnectionScheduling(Integer n, List<Integer> W, List<Integer> C) {
for (int m = 0; m < n; m++) {
if (W.get(m) > 0) {
for (int i = m + 1; i < n; i++) {
if (C.get(m) * W.get(i) > C.get(i) * W.get(m)) {
m = i;
}
}
return m;
}
}
return null;