ip_vs 原理解析 (三)调度器

这篇具有很好参考价值的文章主要介绍了ip_vs 原理解析 (三)调度器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

调度器

ipvs 的 调度器(scheduler) 有很多种,这里不详细介绍各个调度器的算法,主要关注于 ipvs 流程中的调度器注册和使用。

ipvs 的调度器有 rr(轮询),wrr(加权轮询),lc(最小链接),sh(源地址散列),sed(最短预期延时) 等等

注册

每个调度器都是通过 module_init() 进行初始化

rr 调度器

static struct ip_vs_scheduler ip_vs_rr_scheduler = {
	.name =			"rr",			/* name */
	.refcnt =		ATOMIC_INIT(0),
	.module =		THIS_MODULE,
	.n_list =		LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
	.init_service =		ip_vs_rr_init_svc,
	.add_dest =		NULL,
	.del_dest =		ip_vs_rr_del_dest,
	.schedule =		ip_vs_rr_schedule,
};

static int __init ip_vs_rr_init(void)
{
	return register_ip_vs_scheduler(&ip_vs_rr_scheduler);
}

module_init(ip_vs_rr_init);

register_ip_vs_scheduler 调度函数
将调度器链接在全局链表 ip_vs_schedulers 上

调度器绑定 svc

在第一节 ipvsadm 创建 svc 时 ip_vs_bind_scheduler 会为 svc 绑定调度器

ip_vs_bind_scheduler
  | -- init_service       执行调度器的 init_service 函数,调度器
  | -- rcu_assign_pointer(svc->scheduler, scheduler) 将调度器结构赋予虚拟服务结构的 scheduler 成员

看一下 rr 的 init_service

ip_vs_rr_init_svc
  | -- svc->sched_data = &svc->destinations;      将 rs 链表赋予 svc 的调度器应用 data,svc->sched_data

看一下 wrr 的 init_service

static int ip_vs_wrr_init_svc(struct ip_vs_service *svc)
{
	struct ip_vs_wrr_mark *mark;

	mark = kmalloc(sizeof(struct ip_vs_wrr_mark), GFP_KERNEL);
	if (mark == NULL)
		return -ENOMEM;

	mark->cl = list_entry(&svc->destinations, struct ip_vs_dest, n_list);       // 后端链表
	mark->di = ip_vs_wrr_gcd_weight(svc);                                                  // 计算最大公约数的方法,即权重步长
	mark->mw = ip_vs_wrr_max_weight(svc) - (mark->di - 1);                     // 最大权重计算方法
	mark->cw = mark->mw;                                                                           // 当前权重
	svc->sched_data = mark;

	return 0;
}

ip_vs_schedule 结构体

接着看 ip_vs_rr_scheduler
其中的 .schedule 即调度方法,如 rr 的 ip_vs_rr_schedule

static struct ip_vs_dest *
ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
		  struct ip_vs_iphdr *iph)
{
	struct list_head *p;
	struct ip_vs_dest *dest, *last;
	int pass = 0;

	IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);

	spin_lock_bh(&svc->sched_lock);
	p = (struct list_head *) svc->sched_data;
	last = dest = list_entry(p, struct ip_vs_dest, n_list);

	do {
		list_for_each_entry_continue_rcu(dest,
						 &svc->destinations,
						 n_list) {
			if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
			    atomic_read(&dest->weight) > 0)
				/* HIT */
				goto out;
			if (dest == last)
				goto stop;
		}
		pass++;
		/* Previous dest could be unlinked, do not loop forever.
		 * If we stay at head there is no need for 2nd pass.
		 */
	} while (pass < 2 && p != &svc->destinations);

stop:
	spin_unlock_bh(&svc->sched_lock);
	ip_vs_scheduler_err(svc, "no destination available");
	return NULL;

  out:
	svc->sched_data = &dest->n_list;
	spin_unlock_bh(&svc->sched_lock);
	IP_VS_DBG_BUF(6, "RR: server %s:%u "
		      "activeconns %d refcnt %d weight %d\n",
		      IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
		      atomic_read(&dest->activeconns),
		      refcount_read(&dest->refcnt), atomic_read(&dest->weight));

	return dest;
}

可以看到轮询的调度算法,svc->sched_data 是当前链表中后端的指针,当调度时,将之前的后端赋值给 last,然后循环链表给 dst,如果循环到的 dst 可用,即 goto out,设置 sched_data 为当前调度到的后端的指针,然后返回当前后端。

其中的 .add_dest 和 .del_dest 即增加和删除 后端的操作,像 rr 算法添加 后端时不需要调整,但删除时需要 ip_vs_rr_del_dest。

static int ip_vs_rr_del_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest)
{
	struct list_head *p;

	spin_lock_bh(&svc->sched_lock);
	p = (struct list_head *) svc->sched_data;
	/* dest is already unlinked, so p->prev is not valid but
	 * p->next is valid, use it to reach previous entry.
	 */
	if (p == &dest->n_list)
		svc->sched_data = p->next->prev;
	spin_unlock_bh(&svc->sched_lock);
	return 0;
}

在删除的 后端是当前调度的后端时的情况,这个时候将当前调度的后端改为当前节点在链表的前一个,这样后续调度时也能正常调度到当前节点的下一个。

像 wrr 添加 dst,删除 dst,更新 dst,都需要 ip_vs_wrr_dest_changed,这是由于权重变更后,有可能最大权重,最大公约数都会变化,需要更新整个 svc->sched_data。由此看出,后端的变化会即时更新调度算法。

PE

持久化引擎,当前 ip_vs 只有一种 sip 即源 ip 策略

	.ct_match =		ip_vs_sip_ct_match,
static bool ip_vs_sip_ct_match(const struct ip_vs_conn_param *p,
				  struct ip_vs_conn *ct)

{
	bool ret = false;

	if (ct->af == p->af &&
	    ip_vs_addr_equal(p->af, p->caddr, &ct->caddr) &&
	    /* protocol should only be IPPROTO_IP if
	     * d_addr is a fwmark */
	    ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
			     p->vaddr, &ct->vaddr) &&
	    ct->vport == p->vport &&
	    ct->flags & IP_VS_CONN_F_TEMPLATE &&
	    ct->protocol == p->protocol &&
	    ct->pe_data && ct->pe_data_len == p->pe_data_len &&
	    !memcmp(ct->pe_data, p->pe_data, p->pe_data_len))
		ret = true;

	IP_VS_DBG_BUF(9, "SIP template match %s %s->%s:%d %s\n",
		      ip_vs_proto_name(p->protocol),
		      IP_VS_DEBUG_CALLID(p->pe_data, p->pe_data_len),
		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
		      ret ? "hit" : "not hit");

	return ret;
}

在 Kubernetes 中,service 的 sessionAffinity: ClientIP 利用了该特性,在 timeout 时间内,同一个 源 ip 的访问会调度到同一个 后端。文章来源地址https://www.toymoban.com/news/detail-626509.html

到了这里,关于ip_vs 原理解析 (三)调度器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 解析 IP(IPv4)地址

    为了保证正常通信,有必要为每个设备配置正确的 IP 地址。在互联网通信中,全世界都必须设定正确的IP地址。否则,根本无法实现正常的通信。而在用 TCP/IP 进行通信时,需要用 IP 地址识别主机和路由器。 IPv4 地址在计算机中是由如下这样构成的 四组二进制数 每组八位二

    2024年04月28日
    浏览(40)
  • 网络层&&IP协议的基本原理 数据链路层&&ARP协议 域名解析以及一些重要技术

    网络层作用:在复杂的网络环境中确定一个合适的路径。 tcp/ip协议,tcp解决可靠性与效率,ip提供在网络中传输的能力。 传输层决定了单次向下交付数据包的大小。 IP(Internet Protocol)协议是一种网络层协议,用于在互联网上进行数据传输。它定义了数据如何在网络中进行分

    2024年02月15日
    浏览(43)
  • linux ipv6动态解析,家庭宽带ipv6搭建外网访问方案,ddns动态解析ipv6,ipv6建站等

    注意:ipv6和ipv4之间不可互相访问!!! 如题: 1、先确认我们本地是否有公网ipv6地址 Windows查看方法:打开cmd、输入ipconfig 看到有2开头的就是公网ipv6了 linux下输入ifconfig即可 再或者通过ipv6test查看,浏览器打开Test your IPv6.即可  如图即可知道自己是否获取到ipv6 2、如果没有

    2024年02月06日
    浏览(56)
  • 软考系分之计算机网络IP地址的表示(IPv4及IPv6)

      本篇介绍计算机网络中的IP地址,在网络工程师的考试中,IP地址是必考内容,但是在系统分析师的考察中,IP地址的考查重点,应该就是IPv4和IPv6的相关概念和IPv4中简单的子网划分计算了。 2.1 IPv4分类表示   IP地址中,机器存放IPv4是32位二进制代码,每隔8位插一个空格

    2024年01月18日
    浏览(49)
  • Linux内核--网络协议栈(五)TCP IP栈的实现原理与具体过程

    一、引言 二、Linux内核的结构 三、Linux网络子系统 四、TCP/IP协议栈 ------4.1、网络架构 ------4.2、协议无关接口 ------4.3、套接口缓存 ------4.4、重要的数据结构 五、网络信息处理流程 ------5.1、硬中断处理 ------5.2、ksoftirqd内核线程处理软中断 ------5.3、网络协议栈处理 ------5.4、

    2024年01月21日
    浏览(69)
  • TCP/IP协议中分包与重组原理介绍、分片偏移量的计算方法、IPv4报文格式

    目录 一、什么是IP分片 二,为什么要进行IP分片 三、IP分片原理及分析 标志字段的作用  下面是标志位在IP首部中的格式以及各个标志的意义:  TTL  Protocol 协议号 分片包文示例: 分片偏移量计算方法:  第一个分片:  第二个分片:  第三个分片: IP分片是网络上传输IP报

    2024年02月02日
    浏览(67)
  • 【昕宝爸爸小模块】Java中Timer实现定时调度的原理(解析)

    Java中的 Timer 类是用于计划执行一项任务一次或重复固定延迟执行的简单工具。它使用一个名为 TaskQueue 的内部类来存储要执行的任务,这些任务被封装为 TimerTask 对象。 Timer 实现定时调度的基本原理: 创建 Timer 对象 :当你创建一个 Timer 对象时,它会实例化一个线程(不是

    2024年01月16日
    浏览(42)
  • 【软考网络管理员】2023年软考网管初级常见知识考点(10)- 网际协议IP及IPV6,IPV4详解

    分类的IP地址,子网划分,CIDR和路由汇聚,IPV4数据报格式,IPV6协议,软考网络管理员常考知识点,软考网络管理员网络安全,网络管理员考点汇总。 原创于:CSDN博主-《拄杖盲学轻声码》,更多考点汇总可以去他主页查看 更多考试总结可关注CSDN博主-《拄杖盲学轻声码》 这

    2024年02月11日
    浏览(44)
  • vmware虚拟机网络“桥接模式”与“NAT模式”的联网原理及linux环境下IP配置指引

    选中虚拟机》设置》网络适配器,打开虚拟机设置面板 我们看到网络连接处有多个选项,今天 良哥 通过试验告诉你“桥接模式”和“NAT模式”的联网原理、区别及两种模式下IP地址配置的详细方法。 桥接模式 ①虚拟机操作系统直接连接物理网卡,通过物理网卡与外部网络建

    2024年02月08日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包