IPVS调度算法之SED
程序员文章站
2024-03-13 15:42:39
...
SED(Shortest Expected Delay)调度算法,将新连接调度到延迟最小的真实服务器。
调度器注册
SED调度器的定义结构为ip_vs_sed_scheduler,使用函数register_ip_vs_scheduler注册到IPVS的调度器系统中。
static struct ip_vs_scheduler ip_vs_sed_scheduler =
{
.name = "sed",
.refcnt = ATOMIC_INIT(0),
.module = THIS_MODULE,
.n_list = LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list),
.schedule = ip_vs_sed_schedule,
};
static int __init ip_vs_sed_init(void)
{
return register_ip_vs_scheduler(&ip_vs_sed_scheduler);
}
调度处理
在此SED算法中,使用以下函数ip_vs_sed_dest_overhead计算每个真实服务器的OverHead,由代码可知结果为真实服务器上的活动连接数额外加1。
static inline int ip_vs_sed_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;
}
调度处理函数ip_vs_sed_schedule,遍历虚拟服务所关联的真实服务器链表,找到第一个非过载并且权重值大于0的真实服务器,计算其OverHead。如果找不到则调度失败。
static struct ip_vs_dest *ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, struct ip_vs_iphdr *iph)
{
struct ip_vs_dest *dest, *least;
int loh, doh;
list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && atomic_read(&dest->weight) > 0) {
least = dest;
loh = ip_vs_sed_dest_overhead(least);
goto nextstage;
}
}
ip_vs_scheduler_err(svc, "no destination available");
return NULL;
从以上选中的真实服务器开始,继续遍历虚拟服务关联的真实服务器链表,直到找到一个负荷最小的真实服务器。
/* Find the destination with the least load.
*/
nextstage:
list_for_each_entry_continue_rcu(dest, &svc->destinations, n_list) {
if (dest->flags & IP_VS_DEST_F_OVERLOAD)
continue;
doh = ip_vs_sed_dest_overhead(dest);
if ((__s64)loh * atomic_read(&dest->weight) > (__s64)doh * atomic_read(&least->weight)) {
least = dest;
loh = doh;
}
}
return least;
}
负荷的计算公式为:OverHead / Weight,两个真实服务器的负荷比较公式如下:
OH1/W1 > OH2/W2 转换为乘法为:
OH1*W2 > OH2*W1
以上条件判断如果成立,表明OH1的负荷大于OH2的负荷,
内核版本 4.15
上一篇: java实现微博后台登录发送微博