欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

IPVS调度算法之LC

程序员文章站 2024-03-13 15:47:27
...

LC(Least-Connection)调度算法,将连接调度到连接数量较少的真实服务器。

调度器注册

由以下的调度器结构定义ip_vs_lc_scheduler可知,此调度器比较简单,仅实现了schedule指针函数。

static struct ip_vs_scheduler ip_vs_lc_scheduler = {
    .name =                 "lc",
    .refcnt =               ATOMIC_INIT(0),
    .module =               THIS_MODULE,
    .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
    .schedule =             ip_vs_lc_schedule,
};

static int __init ip_vs_lc_init(void)
{
    return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ;
}

调度处理

LC调度算法的基础是每个真实服务器的连接数量,由以下函数ip_vs_dest_conn_overhead进行计算。内核在此处假设真实服务器处理每个活动连接的消耗比处理每个不活动连接的消耗高出256倍,这个倍数是估算值,之后有可能会改变。计算真实服务器整体消耗的公式为:活动连接数量*256 + 非活动连接数量。

static inline int ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
{
    /* We think the overhead of processing active connections is 256
     * times higher than that of inactive connections in average. (This
     * 256 times might not be accurate, we will change it later) We
     * use the following formula to estimate the overhead now:
     *        dest->activeconns*256 + dest->inactconns
     */
    return (atomic_read(&dest->activeconns) << 8) +
        atomic_read(&dest->inactconns);
}

以下为LC算法的调度函数ip_vs_lc_schedule。首先明确一点,如果真是服务器以及过载(标志IP_VS_DEST_F_OVERLOAD),或者权重等于零(weight==0),将不再调度新的连接到此真实服务器。

权重为零的真实服务器,虽然不在被分配新的连接,但是仍可处理其上现存的连接。

函数实现比较简单,遍历虚拟服务的destinations真实服务器链表,返回消耗值最小的真实服务器。

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

    /*
     * Simply select the server with the least number of
     *        (activeconns<<5) + inactconns
     * Except whose weight is equal to zero.
     * If the weight is equal to zero, it means that the server is quiesced, the existing connections to the server still get
     * served, but no new connection is assigned to the server.
     */
    list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
        if ((dest->flags & IP_VS_DEST_F_OVERLOAD) || atomic_read(&dest->weight) == 0)
            continue;
        doh = ip_vs_dest_conn_overhead(dest);
        if (!least || doh < loh) {
            least = dest;
            loh = doh;
        }
    }
    return least;
}

内核版本 4.15

相关标签: ipvs