假设有一组服务器(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;