我有一个管道,它在 Linux 机器上运行一些计算密集型任务。启动这些任务的脚本会检查当前的平均负载,如果负载高于某个阈值,则等待负载降至该阈值以下。这是在 Ubuntu 虚拟机上进行的(如果相关,则在 Ubuntu 主机上运行),可以为其分配可变数量的核心。我们的开发和生产机器都是在同一物理服务器上运行的虚拟机,我们会根据需要手动为每台机器分配核心。
我注意到,即使虚拟机只有 20 个核心,~60 的负载也不会导致机器崩溃。我的理解Linux 平均负载的工作原理是,任何超过 CPU 数量的负载都表明存在问题,但显然事情并没有那么明确。
我正在考虑将阈值设置为类似于 的位置$(grep -c processor /proc/cpuinfo) x N
。N>=1
是否有任何巧妙的方法来确定应采用的值N
,以最大化性能并最小化延迟?
换句话说,在性能开始下降之前,我如何知道一台机器可以支持的最大平均负载是多少?我天真地以为那是 CPU 的数量(所以,N=1
),但这似乎站不住脚。由于核心数量可能有所不同,测试可能的组合既复杂又耗时,而且由于这是一台由不同人使用的机器,因此不切实际。
那么,如何根据可用核心数来确定可接受的最大平均负载阈值?
答案1
负载是 Linux 上经常被误解的一个值。
在 Linux 上,它是对处于运行或不可中断睡眠状态的所有任务的测量。
注意这是任务,而不是进程。该值包含线程。
内核每五秒钟计算一次负载,并取加权平均值。也就是说,一分钟负载是 5/60 的平均值,五分钟是 5/300 的平均值,十五分钟是 5/900 的平均值。
一般来说,负载作为一个纯数字,如果没有参考点就没有什么价值,而且我认为这个值经常被歪曲。
误解 1:负荷是比率
换句话说,我如何才能知道在性能开始下降之前机器可以支持的最大平均负载是多少?
这是人们对 Linux 负载最常见的误解。它可以用来衡量 CPU 性能与某个固定比率的关系。这是不是给你带来什么负荷。
详细来说 - 人们很容易理解 CPU 利用率。这是一段时间内的效用。你把已完成的工作除以可能完成的工作。
这方面可能的工作是一个固定的已知值,通常以 100 的百分比表示 - 这就是您的固定比率。
然而,负载没有限制。没有固定的最大值,这就是为什么您很难理解要衡量什么。
澄清什么是采样负载做有一个不固定的最大值,即采样时系统中当前存在的任务总数(这与正在进行的 CPU 工作没有实际关系)。
计算负载时没有固定的最大值,因为它会被纳入加权平均值,并且在测量权重时不会记录任务的数量。
因为我喜欢食物,所以你可以打个比方,利用率是你吃完盘子里食物的速度,而装载量——平均而言——是你还剩下多少盘子可以吃。
因此,CPU 效用和负载之间的区别很微妙,但很重要。CPU 效用是衡量正在进行的工作负载是衡量需要做的工作。
误解2:负载是即时测量的
第二个谬误是,负载是一种精细的测量。你可以读一个数字来了解系统的状态。
负载不是粒度级的,而是代表系统的一般长期状况。它不仅每五秒采样一次(因此会错过 5 秒窗口内发生的正在运行的任务),而且分别以 1、5 和 15 分钟的平均值进行测量。
您不能将其用作容量的即时衡量标准,而只能作为较长时期内系统负担的总体衡量标准。
负载可能为 100,但 30 秒后又变为 10。您必须持续观察该值才能使用。
Load 能告诉你什么?
它可以让您了解系统的工作趋势。它所承受的压力超过其承受能力,还是低于其承受能力?
- 如果负载小于您拥有的 CPU 数量,这(通常)表明您的 CPU 容量多于工作量。
- 如果负载大于或等于 CPU 数量且呈上升趋势,则表明系统的工作量超出了其处理能力。
- 如果负载大于或等于 CPU 数量并且呈下降趋势,则表明系统完成工作的速度比您分配给它的速度快。
由于不间断的睡眠状态,这确实会使负载值变得模糊,成为纯粹的工作调度分数 - 但可以表明磁盘上的需求量有多大(从技术上讲,这仍然是需要完成的工作)。
负载也为系统异常提供线索。如果您看到负载超过 50,则表明存在问题。
额外的负荷会引起人们毫无缘由的担心。
- 众所周知,椎间盘活动可以增加负荷。
- 如果大量进程绑定到一个正在等待的 CPU,则负载可能会人为地膨胀。
- 优先级(优良性)非常低的任务通常会等待很长时间,以便为该特定进程增加 1 的负载。
总之
我发现负载是一个非常模糊的值,确切地说,它没有绝对值。在一个系统上获得的测量值与另一个系统相比往往毫无意义。
这可能是我在 top 中看到的第一件事之一,纯粹是为了检查是否存在明显异常。基本上,我几乎把它当成温度计来使用——就像系统的一般状况一样。
我发现它的采样周期对于我投入系统的大多数工作负载来说都太长了(通常以秒为单位,而不是几分钟)。我想这对于执行长时间运行的密集型任务的系统来说是有意义的,但我实际上并不经常这样做。
我使用它的另一个目的是进行长期容量管理。绘制长期(几个月)的图表是一件好事,因为您可以使用它来了解与几个月前相比,您处理的工作量增加了多少。
最后,回答您关于在您的场景中该做什么的问题。老实说,我给出的最佳建议是,不要考虑使用负载作为何时运行的因素 - 使用 nice 来执行您的进程,并让其他进程优先于它。这有几个好处。
- 当其他进程繁忙时,您只需为该进程提供少量的 CPU 时间。
- 如果 CPU 上没有任何内容或 CPU 处于空闲状态,则您的任务会将 100% 的时间花在其上。
- 进程组中的所有进程都继承了相同的优缺点。
当 niceness 为 0(默认值)时,每个进程的权重为 1024。权重越低,为进程提供的 CPU 时间越少。以下是此行为的表格。
Nice Weight
0 1024
1 820
2 655
3 526
4 423
5 335
6 272
7 215
8 172
9 137
10 110
11 87
12 70
13 56
14 45
15 36
16 29
17 23
18 18
19 15
比较一下,在有 2 个进程等待运行的场景中 - 如果您将进程的优先级重新设置为 +10,它将获得优先级为 0 的进程所拥有的 CPU 时间的大约 1/10。如果您将其重新设置为 +19,它将获得优先级为 0 的进程所拥有的 CPU 时间的 1/100。
值得注意的是,你可能会看到你的负载为 1至少在您的管道持续期间。
我想这将是解决您问题的一个更优雅的解决方案。
答案2
从维基百科:
然而,Linux 还包括处于不间断睡眠状态的进程(通常等待磁盘活动),如果由于 I/O 系统繁忙或停滞而导致许多进程在 I/O 中处于阻塞状态,则可能导致截然不同的结果
换句话说,Linux 报告的平均负载包括任何等待 I/O 的进程(例如:磁盘或网络)。这意味着,如果您的应用程序在某种程度上是 I/O 密集型的,那么您将获得较高的平均负载(即:许多进程正在等待 I/O),而 CPU 利用率较低(它们在等待 I/O 时处于休眠状态)。
反过来,这将导致系统即使在平均负载过重的情况下也能做出响应。