| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> linux进程管理(二十五)—负载均衡 -> 正文阅读 |
|
[系统运维]linux进程管理(二十五)—负载均衡 |
linux进程管理—负载均衡前面主要是学习进程的调度管理,默认都是在单CPU上的调度策略,在O(1)调度后,为了减小CPU之间的干扰,就会为每个CPU上分配一个任务队列,运行的时候可能会出现有的CPU很忙,有的CPU很闲,为了避免这个问题的出现,甚至最极端的情况是,一个 CPU 的可运行进程队列拥有非常多的进程,而其他 CPU 的可运行进程队列为空,这就是著名的 1 什么是CPU负载提到负载,我们首先会想到命令uptime或者top命令输出系统的平均负载(load average),例如uptime的输出结果
load average的三个值分别代表过去1分钟、5分钟、15分钟的系统平均负载,这三个值实际上来自于 CPU负载(
从系统的角度而言,平均负载反映了系统面临的总体压力,而如果我们将视角切换到任务本身的化,那么从本质上说,系统负载代表着任务对系统资源的渴求程度。 从负载的定义是处于
所以通过负载,我们直觉的认为,一个队列上挂着10个任务的CPU承受的压力比挂着5个任务的负载要更重一些,早期的CPU负载是使用runqueue深度来描述的。所以使用runqueue是一个比较粗略
那么仅仅通过runqueue深度来描述CPU负载就有点问题,因此现代调度器使用Cpu runqueue上task load之和来表示cpu的负载,这样就变成对任务的负载跟自动,linux3.8版本的linux内核引入了PELT算法来跟踪每一个sched entity的负载,把负载跟踪的算法从per-CPU进化到per-entity。PELT算法不但能知道CPU的负载,而且知道负载来自哪一个调度实体,从而可以更精准的进行负载均衡。 2 什么是均衡无论是单核还是多核,只要是多任务系统,就需要调度,但调度对多核系统显得尤为重要,因为调度不当,会无法充分发挥多核的潜力。 基于多核的调度,大致有两种模型,一种是只有一个任务队列(single queue),即当有一个任务需要执行时,选择一个空闲的CPU来承接。 这种调度方法可谓简单明了,但既然共享一个队列,那往往免不了需要上锁。此外,现代CPU可是使用了cache的,一个任务一会儿在这个CPU上运行,一会儿又在那个CPU上运行,每新到一处,cache往往都是“冷”的,执行效率必然大打折扣。 所以,任务既然交给了一个CPU做,就让它一直做嘛,各管各的,一竿子到底。从OS调度的角度,就是采用每个CPU有一个任务队列的模型(multiple queues)。 共享减少了,cache affinity(俗称"cpu affinity")也建立起来了,但新的问题也随之出现了。同时现在的CPU架构策略,对于均衡的策略也是有很大的影响soc上对于CPU的拓扑关系,我们知道目前如手机的系统都是采用的是SMP的架构,比如一个4核心的SOC,一大(更高的运算能力)一小(更低的功耗),两个核心一个cluster,那么每个cluster可以认为是一个调度域,每个MC调度域中有两个调度组,每个调度组中只有一个CPU。跨cluster的负载均衡是需要清除L2 cache的,开销是很大的,因此SOC级别的DIE调度域进行负载均衡的开销会更大一些。 我们假设整个系统如果有800的负载,那么每个CPU上分配400的负载其实是不均衡的,因为大核CPU可以提供更强的算力。这样就会导致大核供给不足,而小核会出现过度供给。所以需要有两个和运算力相关的参数
有了各个任务负载,将runqueue中的任务负载累加起来就可以得到CPU负载,配合系统中各个CPU的算力,看起来我们就可以完成负载均衡的工作,然而事情没有那么简单,当负载不均衡的时候,任务需要在CPU之间迁移,不同形态的迁移会有不同的开销。例如一个任务在小核cluster上的CPU之间的迁移所带来的性能开销一定是小于任务从小核cluster的CPU迁移到大核cluster的开销。因此,为了更好的执行负载均衡,我们需要构建和CPU拓扑相关的数据结构,也就是调度域和调度组的概念。 3 如何负载要实现多核系统的负载均衡,主要依靠task在不同CPU之间的迁移(migration),也就是将一个task从负载较重的CPU上转移到负载相对较轻的CPU上去执行。从CPU的runqueue上取下来的这个动作,称为"pull",放到另一个CPU的runqueue上去,则称之为"push"。 负载均衡有两种方式:pull, push
但是迁移是有代价的。在同一个物理CPU的两个logical core之间迁移,因为共享cache,代价相对较小。如果是在两个物理CPU之间迁移,代价就会增大。更进一步,对于NUMA系统,在不同node之间的迁移将带来更大的损失。 这其实形成了一个调度上的约束,在Linux中被实现为"sched domain",并以hierarchy的形式组织。处于同一内层domain的,迁移可以更频繁地进行,越往外层,迁移则应尽可能地避免。 一个CPU拓扑示例 我们以一个4小核+4大核的处理器来描述CPU的domain和group: 在上面的结构中,sched domain是分成两个level,base domain称为MC domain(multi core domain),顶层的domain称为DIE domain。顶层的DIE domain覆盖了系统中所有的CPU,小核cluster的MC domain包括所有小核cluster中的cpu,同理,大核cluster的MC domain包括所有大核cluster中的cpu。
为了减少锁的竞争,每一个cpu都有自己的MC domain和DIE domain,并且形成了sched domain之间的层级结构。在MC domain,其所属cpu形成sched group的环形链表结构,各个cpu对应的MC domain的groups成员指向环形链表中的自己的cpu group。在DIE domain,cluster形成sched group的环形链表结构,各个cpu对应的DIE domain的groups成员指向环形链表中的自己的cluster group。 4 调度域(sched domain)和调度组(sched group)负载均衡的复杂性主要和复杂的系统拓扑有关。由于当前CPU很忙,我们把之前运行在该CPU上的一个任务迁移到新的CPU上的时候,如果迁移到新的CPU是和原来的CPU在不同的cluster中,性能会受影响(因为会cache flush)。 但是对于超线程架构,cpu共享cache,这时候超线程之间的任务迁移将不会有特别明显的性能影响。NUMA上任务迁移的影响又不同,我们应该尽量避免不同NUMA node之间的任务迁移,除非NUMA node之间的均衡达到非常严重的程度。 总之,一个好的负载均衡算法必须适配各种cpu拓扑结构。为了解决这些问题,linux内核引入了sched_domain的概念,CPU对应的调度域和调度组可通过在设备模型文件/proc/sys/kernel/sched_domain/中查看。 调度组: 调度组是组成调度域的基本单位,在最小的调度域中一个cpu core是一个调度组,在最大的调度域中,一个NUMA结点内的所有cpu core成一个调度组。 调度域: 上述结构中有3个调度域
调度域并不是一个平层结构,而是根据CPU拓扑形成层级结构。相对应的,负载均衡也不是一蹴而就的,而是会在多个sched domain中展开(例如从base domain开始,一直到顶层sched domain,逐个domain进行均衡)。内核中struct sched_group来描述调度组,其主要的成员如下:
5 何时均衡作为OS的心跳,只要不是NO_HZ的CPU,tick都会如约而至,这为判断是否需要均衡提供了一个绝佳的时机。不过,如果在每次tick时钟中断都去做一次balance,那开销太大了,所以balance的触发是有一个周期要求的。当tick到来的时候,在scheduler_tick函数中会调用trigger_load_balance来触发周期性负载均衡,相关的代码如下:
进行调度和均衡本身也是需要消耗CPU的资源,因此比较适合交给idle的CPU来完成,idle_cpu被选中的这个idle CPU被叫做"idle load balancer"。
如上流程图,实际上内核的负载均衡有以下几种
如果没有dynamic tick特性,那么其实不需要进行nohz idle load balance,因为tick会唤醒处于idle的cpu,从而周期性tick就可以覆盖这个场景。
由于idle状态的CPU通常处于tickless/nohz模式,所以需要向它发送IPI(核间中断)来唤醒(“kick”),这也是为什么实现此过程的函数被命名为"nohz_balancer_kick"。 作为idle的CPU收到IPI后,将在softirq上下文中(类型为"SCHED_SOFTIRQ")执行负载均衡,其对应的处理函数是在初始化时就注册好了的。
这段最重要的是在内核中注册了一个软中断来做负载均衡run_rebalance_domains
这里暂时先不考虑nohz相关的函数,从rebalance_domains开始入手
该函数流程如下: 当一个CPU上进行负载均衡的时候,总是从base domain开始,检查其所属的sched group之间的负载均衡情况,如果有不均衡的情况,那么会在该CPU所属的cluster之间进行迁移,以维护cluster内各个CPU任务的负载均衡。 所以rebalance_domains职责是寻找需要被balance的sched domain,然后通过"find_busiest_group"找到该domain中最繁忙的sched group,进而通过"find_busiest_queue"在这个最繁忙的group中挑选最繁忙的CPU runqueue,被选中的CPU就成为任务迁移的src。
这里有一个例外,设置了CPU affinity,和所在CPU进行了绑定(俗称被"pin"住)的任务不能被迁移(就像被pin住的内存page不能被swap到磁盘上一样),对此进行判断的函数是"can_migrate_task"。 需要注意的是,对于CFS调度,任务迁移到一个新的runqueue之后,其在之前runqueue上的vruntime值就不适用了,需要重新进行计算和矫正,否则可能造成“不公平”(详情可参考这篇文章)。 6 总结
(1)判断该任务是否适合当前CPU算力 (2)如果判定需要均衡,那么需要在CPU之间迁移多少的任务才能达到平衡?有了任务负载跟踪模块,这个问题就比较好回答了。
(1)在MC domain上,我们会对跟踪每个CPU负载状态(sched group只有一个CPU)并及时更新其算力,使得每个CPU上有其匹配的负载。 (2)在DIE domain上,我们会跟踪cluster上所有负载(每个cluster对应一个sched group)以及cluster的总算力,然后计算cluster之间负载的不均衡状况,通过inter-cluster迁移让整个DIE domain进入负载均衡状态
我们以周期性均衡为例来描述负载均衡的基本过程,当一个CPU上进行周期性负载均衡的时候,我们总是从base domain开始,检查其所属sched group之间(即各个cpu之间)的负载均衡情况,如果有不均衡情况,那么会在该cpu所属cluster之间进行迁移,以便维护cluster内各个cpu core的任务负载均衡。 MC domain的均衡大致需要下面几个步骤:
完成MC domain均衡之后,继续沿着sched domain层级结构向上检查,进入DIE domain,在这个level的domain上,我们仍然检查其所属sched group之间(即各个cluster之间)的负载均衡情况,如果有不均衡的情况,那么会进行inter-cluster的任务迁移。基本方法和MC domain类似,只不过在计算均衡的时候,DIE domain不再考虑单个CPU的负载和算力,它考虑的是: (1)该sched group的负载,即sched group中所有CPU负载之和 (2)该sched group的算力,即sched group中所有CPU算力之和 参考资料http://www.wowotech.net/process_management/load_balance.html https://zhuanlan.zhihu.com/p/126291950 https://www.cnblogs.com/LoyenWang/p/12316660.html https://www.codenong.com/cs107028338/ |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/16 7:22:01- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |