IPVS调度算法之NQ

NQ(Never Queue)调度算法,即当真实服务器中有空闲的时,先调度到空闲服务器,否则依据SED算法调度。

调度器注册

NQ调度器的定义结构为ip_vs_nq_scheduler,使用函数register_ip_vs_scheduler注册到IPVS的调度器系统中。

static struct ip_vs_scheduler ip_vs_nq_scheduler =
{
        .name =                 "nq",
        .refcnt =               ATOMIC_INIT(0),
        .module =               THIS_MODULE,
        .n_list =               LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
        .schedule =             ip_vs_nq_schedule,
};

static int __init ip_vs_nq_init(void)
{
        return register_ip_vs_scheduler(&ip_vs_nq_scheduler);
}

调度处理

首先看一下NQ算法中真实服务器的Overhead的计算函数,可见,其与调度器SED(Shortest Expected Delay)中的Overhead计算一致。

static inline int ip_vs_nq_dest_overhead(struct ip_vs_dest *dest)
{
        /* We only use the active connection number in the cost calculation here.
         */
        return atomic_read(&dest->activeconns) + 1;
}

以下为NQ调度算法处理函数ip_vs_nq_schedule,在遍历虚拟服务所关联的真实服务器链表时,首先选择还没有任何活动连接的真实服务器。否则,选择负荷最小的真实服务器,每个真实服务器负荷的计算与SED调度器相同。

static struct ip_vs_dest *ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, struct ip_vs_iphdr *iph)
{
    struct ip_vs_dest *dest, *least = NULL;
    int loh = 0, doh;

    list_for_each_entry_rcu(dest, &svc->destinations, n_list) {

        if (dest->flags & IP_VS_DEST_F_OVERLOAD || !atomic_read(&dest->weight))
            continue;

        doh = ip_vs_nq_dest_overhead(dest);

        /* return the server directly if it is idle */
        if (atomic_read(&dest->activeconns) == 0) {
            least = dest;
            loh = doh;
            goto out;
        }

        if (!least ||
            ((__s64)loh * atomic_read(&dest->weight) > (__s64)doh * atomic_read(&least->weight))) {
                least = dest;
                loh = doh;
        }
    }

真实服务器负荷等于其overHead除以其权重Weight,以下为比较两个真实服务器负荷的公式:

h1/w1 > h2/w2

如果以上条件语句成立,表明真实服务器h1的负荷大于h2的负荷。将以上等式变换为乘法操作,如下:

h1*w2 > h2*w1

内核版本 4.15

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页