Linux负载平均值 (Load Average):解开谜团

这篇博客探讨了Linux系统负载平均值的神秘之处,解释了它不仅包括CPU活动,还涵盖了不可中断任务(如磁盘I/O)。作者追溯了这个变化的历史,揭示了1993年补丁的原始意图,即反映系统整体资源需求。文章提供了负载平均值与其他指标(如CPU利用率、磁盘I/O)的比较,并讨论了如何通过火焰图来分析不可中断任务。最后,作者建议结合多种指标来理解系统性能,同时指出平均负载在云扩展策略中的作用。
摘要由CSDN通过智能技术生成

原文

负载平均值 (Load Average) 是一个行业关键指标——我的公司花了数百万美元根据它们和其他指标自动扩展云实例——但在Linux上,它们有一些神秘之处。Linux负载平均值不仅跟踪可运行任务,还跟踪处于不可中断睡眠状态的任务。为什么?我从来没见过解释。在这篇文章中,我将解开这个谜团,并总结负载平均值,作为每个试图解释它们的人的参考。

Linux负载平均值是“系统负载平均值”,它将系统上正在运行的线程(任务)需求显示为正在运行的线程加上等待的线程的平均数。这衡量的是需求,需求可能大于系统当前处理的需求。大多数工具显示1、5和15分钟的三个平均值:

$ uptime
 16:48:24 up  4:11,  1 user,  load average: 25.25, 23.40, 23.46

top - 16:48:42 up  4:12,  1 user,  load average: 25.25, 23.14, 23.37

$ cat /proc/loadavg 
25.72 23.19 23.35 42/3411 43603

一些解释:

  • 如果平均值为0.0,则系统处于空闲状态。
  • 如果1分钟的平均值高于5或15分钟的平均值,则负载增加。
  • 如果1分钟的平均值低于5分钟或15分钟的平均值,则负载降低。
  • 如果它们高于你的CPU核心数,则可能存在性能问题(具体取决于)。

作为三个集合,你可以判断负载是增加还是减少,这很有用。当需要单个需求值时,它们也很有用,例如用于云自动缩放规则。但如果没有其他指标的帮助,很难更详细地理解它们。单个值23-25本身并不意味着什么,但如果CPU核心数已知,并且已知是CPU绑定的工作负载,则可能意味着什么。

我通常切换到其他指标,而不是尝试调试平均负载。我将在接近结尾的“更好的指标”部分讨论这些问题。

历史

最初的平均负载仅显示CPU需求:正在运行的进程数加上等待运行的进程数。1973年8月,RFC 546题为“TENEX平均负荷”中对此有一个很好的描述:

[1] TENEX负载平均值是衡量CPU需求的指标。平均负载是给定时间段内可运行进程数的平均值。例如,平均每小时负载为10意味着(对于单个CPU系统),在该小时内的任何时间,都可能看到1个进程正在运行,9个其他进程准备运行(即,未阻塞在I/O上)等待CPU。

ietf.org上的版本链接到1973年7月手绘的负荷平均图的PDF扫描,显示这已经被监控了几十年:
ietf.org

如今,旧操作系统的源代码也可以在网上找到。以下是TENEX(1970年代早期)SCHED.MAC中的DEC宏汇编:

NRJAVS==3               ;NUMBER OF LOAD AVERAGES WE MAINTAIN
GS RJAV,NRJAVS          ;EXPONENTIAL AVERAGES OF NUMBER OF ACTIVE PROCESSES
[...]
;UPDATE RUNNABLE JOB AVERAGES

DORJAV: MOVEI 2,^D5000
        MOVEM 2,RJATIM          ;SET TIME OF NEXT UPDATE
        MOVE 4,RJTSUM           ;CURRENT INTEGRAL OF NBPROC+NGPROC
        SUBM 4,RJAVS1           ;DIFFERENCE FROM LAST UPDATE
        EXCH 4,RJAVS1
        FSC 4,233               ;FLOAT IT
        FDVR 4,[5000.0]         ;AVERAGE OVER LAST 5000 MS
[...]
;TABLE OF EXP(-T/C) FOR T = 5 SEC.

EXPFF:  EXP 0.920043902 ;C = 1 MIN
        EXP 0.983471344 ;C = 5 MIN
        EXP 0.994459811 ;C = 15 MIN

下面是今日Linux的源代码摘录(include/Linux/sched/loadavg.h):

#define EXP_1           1884            /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5           2014            /* 1/exp(5sec/5min) */
#define EXP_15          2037            /* 1/exp(5sec/15min) */

Linux也在硬编码1、5和15分钟常量。
在旧系统中也有类似的负载平均指标,包括 Multics,它具有指数调度队列平均值。

三个数字

这三个数字是1、5和15分钟的平均负荷。但它们不是真正的平均值,也不是1分钟、5分钟和15分钟。从上面的资料中可以看出,1、5和15分钟是方程式中使用的常数,用于计算5秒平均值的指数衰减滚动和。得出的1、5和15分钟的平均负荷反映了远远超过1、5和15分钟的负荷。

如果你使用一个空闲的系统,然后开始一个单线程CPU绑定的工作负载(循环中的一个线程),60秒后一分钟的平均负载是多少?如果它是一个普通的平均值,它将是1.0。这是那个实验,用图表表示:
loadavg
负载平均试验以可视化指数衰减

所谓的“一分钟平均值”仅在一分钟内达到0.62左右。关于这个等式和类似的实验,Neil Gunther博士写了一篇关于平均负载的文章:它是如何工作的,另外 loadavg.c 中有许多Linux源代码块注释。

Linux不可中断任务

当负载平均值首次出现在Linux中时,它们反映了CPU需求,就像其他操作系统一样。但后来Linux将其更改为不仅包括可运行的任务,还包括处于不可中断状态的任务(TASK_UNINTERRUPTIBLE 或 nr_uninterruptible)。此状态用于希望避免信号中断的代码路径,包括磁盘I/O上阻塞的任务和一些锁。你以前可能见过这种状态:它在pstop中显示为“D”状态。ps手册页称之为“不可中断睡眠(通常为IO)”。

不可中断,指的并不是 CPU 不响应外部硬件的中断,而是指进程不响应异步信号。绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的)。

添加不可中断状态意味着Linux平均负载可能会由于磁盘(或NFS)I/O工作负载而增加,而不仅仅是CPU需求。对于熟悉其他操作系统及其CPU负载平均值的人来说,包括这种状态,一开始是非常令人困惑的。

为什么?Linux为什么会这样做?

关于平均负载的文章不计其数,其中许多都指出了Linux nr_uninterruptible 问题。但我没有看到任何解释或甚至冒险猜测它为什么被包括在内。我自己的猜测是,它是为了反映更一般意义上的需求,而不仅仅是CPU需求。

搜索一个古老的Linux补丁程序

理解Linux中发生更改的原因很容易:你可以阅读有关文件的git提交历史记录,并阅读更改描述。我检查了 loadavg.c 上的历史记录,但是添加不可中断状态的更改要早于该文件,该文件是使用早期文件中的代码创建的。我检查了另一个文件,但那条线索也没有用:代码本身在不同的文件间跳跃。为了走捷径,我用 git log -p 转储了整个Linux github 存储库,该存储库有4GB大,并开始反向阅读,以查看代码首次出现的时间。这也是一条死胡同。整个Linux 存储库中最早的修改只追溯到2005年,当时Linus导入了Linux2.6.12-rc2,而这一修改早于2005年。

有历史的Linux 存储库(这里这里),但这些库中也缺少此修改描述。我试图发现,至少当这个变化发生时,我在kernel.org上搜索了tar 包,发现它的修改发生在0.99.15,而不是0.99.13——然而,0.99.14的tar包丢失了。我在其他地方找到了它,并确认修改发生在1993年11月14日的Linux0.99 PatchLevel中。我希望Linus对0.99.14的发布描述能够解释这一变化,但这也是一条死胡同:

“对上一个官方版本(第13页)的更改太多,无法提及(甚至无法记住)…”–Linus

他提到了主要的修改,但没有提到平均负荷的修改。
根据日期,我查阅了内核邮件列表档案以查找实际的补丁,但最早的可用电子邮件是1995年6月,当时系统管理员写道:

“在开发一个使这些邮件档案更有效地扩展的系统时,我意外地破坏了当前的档案集(啊,哦嚯)。”

我的搜索开始感到被诅咒了。谢天谢地,我找到了一些旧的linux-devel邮件列表存档,它们是从服务器备份中解救出来的,通常存储为摘要的tar 包。我搜索了6000多份摘要,其中包含98000多封电子邮件,其中30000封来自1993年。但不知怎么的,他们都不知道。看起来,原来的补丁描述可能会永远消失,而“为什么”仍然是个谜。

不可中断的起源

幸运的是,我终于在oldlinux.org上的一个1993年的压缩邮箱文件中找到了这个变化。这是:

From: Matthias Urlichs <urlichs@smurf.sub.org>
Subject: Load average broken ?
Date: Fri, 29 Oct 1993 11:37:23 +0200

在计算平均负载时,内核只统计“可运行”进程。我不喜欢这样;问题是,正在交换或等待“fast”(即不可中断, I/O)的进程也会消耗资源。
用慢速交换磁盘替换快速交换磁盘时,平均负载下降似乎有些不直观。。。
无论如何,下面的补丁似乎使平均负载与系统的主观速度更加一致。而且,最重要的是,当没有人做任何事情时,负载仍然为零。

--- kernel/sched.c.orig Fri Oct 29 10:31:11 1993
+++ kernel/sched.c  Fri Oct 29 10:32:51 1993
@@ -414,7 +414,9 @@
    unsigned long nr = 0;

    for(p = &LAST_TASK; p > &FIRST_TASK; --p)
-       if (*p && (*p)->state == TASK_RUNNING)
+       if (*p && ((*p)->state == TASK_RUNNING) ||
+                  (*p)->state == TASK_UNINTERRUPTIBLE) ||
+                  (*p)->state == TASK_SWAPPING))
            nr += FIXED_1;
    return nr;
 }
--
Matthias Urlichs        \ XLink-POP N|rnberg   | EMail: urlichs@smurf.sub.org
Schleiermacherstra_e 12  \  Unix+Linux+Mac     | Phone: ...please use email.
90491 N|rnberg (Germany)  \   Consulting+Networking+Programming+etc'ing      42

读到24年前这一变化背后的想法,真是令人惊讶。
这证实了故意更改平均负载以反映对其他系统资源的需求,而不仅仅是CPU。Linux从“CPU平均负载”变为“系统平均负载”。

他使用较慢交换磁盘的例子很有意义:通过降低系统的性能,对系统的需求(测量为运行+排队)应该会增加。但是,平均负载降低了,因为它们只跟踪CPU运行状态,而不跟踪交换状态。Matthias认为这是非直观的,事实就是如此,所以他修正了它。

不可中断的今天

但Linux负载平均值有时不是太高了吗,超过了磁盘I/O的解释?是的,尽管我猜测这是由于一个新的代码路径使用了1993年不存在的 TASK_UNINTERRUPTIBLE 。在Linux0.99.14中,有13个代码路径直接设置 TASK_UNINTERRUPTIBLE 或 TASK_SWAPPING (交换状态后来从Linux中删除)。如今,在Linux4.12中,有近400个代码路径设置了 TASK_UNINTERRUPTIBLE,包括一些锁原语。这些代码路径中的一个可能不应包含在负载平均值中。下次我的平均负载似乎太高时,我会看看是否是这种情况,以及它是否可以被修复。

我给Matthias发了电子邮件(这是第一次),询问他对24年后平均负荷变化的看法。他在一小时内做出了回应(正如我在推特上提到的),并写道:

“平均负荷点”“就是从人的角度得出一个关于系统有多忙的数字。TASK_UNINTERRUPTIBLE 表示进程正在等待磁盘读取之类的操作,这会增加系统负载。磁盘严重受限的系统可能非常缓慢,但 TASK_RUNNING 平均值仅为0.1,这对任何人都没有帮助。”

(如此迅速地得到回复,甚至得到回复,真的让我很开心。谢谢!)

所以马蒂亚斯仍然认为这是有意义的,至少考虑到TASK_UNINTERRUPTIBLE 过去的意思。
但是TASK_UNINTERRUPTIBLE 现在可以匹配更多的东西。我们是否应该将平均负载更改为CPU和磁盘需求?调度器维护人员Peter Zijstra已经向我发送了一个聪明的选项来探索如何做到这一点:将 task_struct->in_iowait 包含在负载平均值中,而不是 TASK_UNINTERRUPTIBLE 中,以便它更接近磁盘I/O。然而,这引出了另一个问题,我们真正想要的是什么?我们是想用线程来衡量对系统的需求,还是仅仅是对物理资源的需求?如果是前者,那么应该包括等待不可中断锁,因为系统需要这些线程。他们不闲着。因此,也许Linux负载平均值已经按照我们希望的方式工作了。

为了更好地理解不可中断代码路径,我想用一种方法来衡量它们的实际效果。然后我们可以研究不同的例子,量化花在这些例子上的时间,看看这些是否都有意义。

测量不可中断任务

下面是一个生产服务器的Off-CPU火焰图,跨越60秒,仅显示内核堆栈,其中我将过滤为仅包括那些处于 TASK_UNINTERRUPTIBLE 状态(SVG)的内核堆栈。它提供了许多不可中断代码路径的示例:

图片链接

先了解什么是off-cpu

  • On-CPU: where threads are spending time running on-CPU.
  • Off-CPU: where time is spent waiting while blocked on I/O, locks, timers, paging/swapping, etc.

如果你不熟悉 off-CPU火焰图:你可以单击帧放大,查看显示为帧塔的完整堆栈。x轴的大小与阻塞CPU的时间成正比,排序顺序(从左到右)没有实际意义。对于 off-CPU堆栈,颜色为蓝色(对于on-CPU堆栈,我使用暖色),饱和度具有随机变化以区分帧。

我使用bcc提供的 offcputime工具(该工具需要Linux 4.8+提供的eBPF功能。该工具用于测量某一进程被阻塞的时间。)和flame graph软件生成了此文件:

# ./bcc/tools/offcputime.py -K --state 2 -f 60 > out.stacks
# awk '{ print $1, $2 / 1000 }' out.stacks | ./FlameGraph/flamegraph.pl --color=io --countname=ms > out.offcpu.svgb>

我正在使用awk将输出从微秒更改为毫秒。offcputime-state2”与TASK_UNINTERRUPTIBLE (参见sched.h)匹配,这是我刚刚为本文添加的一个选项。Facebook的Josef Bacik首先用他的kernelscope 工具实现了这一点,该工具也使用bcc和flame图。在我的示例中,我只是显示内核堆栈,但 offcputime.py 也支持显示用户堆栈。

至于上面的火焰图:它显示60秒中只有926毫秒是在不可中断睡眠中度过的。这只会使我们的平均负荷增加0.015。现在是使用某些cgroup路径的时候了,但是这个服务器没有执行太多的磁盘I/O。
这里有一个更有趣的例子,这次只跨越10秒:

图片链接

右侧的宽塔显示systemd-journalproc_pid_cmdline_read()(见 /proc/PID/cmdline)中被阻塞,导致平均负载为0.07。左侧有一个更宽的页面错误(page fault)的塔,它也以rwsem_down_read_failed()结束(平均负载增加0.23)。我已经使用 flame graph 搜索功能以洋红色突出显示了这些函数。以下是rwsem_down_read_failed() 的摘录:

    /* wait to be given the lock */
    while (true) {
        set_task_state(tsk, TASK_UNINTERRUPTIBLE);
        if (!waiter.task)
            break;
        schedule();
    }

这是使用 TASK_UNINTERRUPTIBLE 的锁获取代码。Linux具有互斥获取函数的不可中断和可中断版本(例如,mutex_lock()mutex_lock_interruptible()以及信号量的down()down_interruptible()。可中断版本允许任务被信号中断,然后在获取锁之前唤醒并处理它。不可中断锁定休眠的时间通常不会对平均负载增加太多,但在这种情况下,它们会增加0.30。如果这个值更高,那么就值得分析一下,看看是否可以减少锁争用(例如在systemd-journalproc_pid_cmdline_read())上挖掘,这将提高性能并降低平均负载。

将这些代码路径包括在平均负载中有意义吗?是的,我会这么说。这些线程是在做工作的中间,并碰巧锁定在一个锁上。他们不闲着。它们是对系统的需求,尽管是对软件资源而不是硬件资源的需求。

分解Linux负载平均值

Linux负载平均值是否可以完全分解为组件?这里有一个例子:在一个空闲的8CPU系统上,我启动了tar来归档一些未缓存的文件。它花费了几分钟的时间,大部分时间被磁盘读取阻塞。以下是从三个不同的终端窗口收集的统计数据:

terma$ pidstat -p `pgrep -x tar` 60
Linux 4.9.0-rc5-virtual (bgregg-xenial-bpf-i-0b7296777a2585be1)     08/01/2017  _x86_64_    (8 CPU)

10:15:51 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:16:51 PM     0     18468    2.85   29.77    0.00   32.62     3  tar

termb$ iostat -x 60
[...]
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.54    0.00    4.03    8.24    0.09   87.10

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvdap1            0.00     0.05   30.83    0.18   638.33     0.93    41.22     0.06    1.84    1.83    3.64   0.39   1.21
xvdb            958.18  1333.83 2045.30  499.38 60965.27 63721.67    98.00     3.97    1.56    0.31    6.67   0.24  60.47
xvdc            957.63  1333.78 2054.55  499.38 61018.87 63722.13    97.69     4.21    1.65    0.33    7.08   0.24  61.65
md0               0.00     0.00 4383.73 1991.63 121984.13 127443.80    78.25     0.00    0.00    0.00    0.00   0.00   0.00

termc$ uptime
 22:15:50 up 154 days, 23:20,  5 users,  load average: 1.25, 1.19, 1.05
[...]
termc$ uptime
 22:17:14 up 154 days, 23:21,  5 users,  load average: 1.19, 1.17, 1.06

我还收集了不可中断状态(SVG)的off-CPU火焰图:

图片链接

最后一分钟的平均负荷为1.19。让我来分解一下:

  • 0.33来自tar的CPU时间(pidstat)
  • 0.67是从tar的不可中断磁盘读取推断出来的(offcpu flame graph的这个值是0.69,我怀疑是因为它开始收集的时间稍晚,跨越的时间范围稍有不同)
  • 0.04来自其他CPU消费者(iostat用户+系统,减去pidstat中tar的CPU)
  • 0.11来自内核工作者不可中断磁盘I/O时间,刷新磁盘写入(offcpu火焰图,左边的两个塔)

这加起来是1.15。我仍然缺少0.04,其中一些可能是舍入和测量间隔偏移误差,但很多可能是由于负载平均值是指数衰减移动和,而我使用的其他平均值(pidstat、iostat)是正常平均值。在1.19之前,一分钟的平均值是1.25,所以其中一些仍然会把我们拉高。有多少?从我之前的图表来看,在一分钟的时候,62%的指标都是从那一分钟开始的,其余的都是旧的。所以0.62x1.15+0.38x1.25=1.18。这与报告的1.19相当接近。

这是一个系统,其中一个线程(tar)加上多一点(内核工作线程中的一些时间)正在工作,Linux报告平均负载为1.19,这是有意义的。如果它测量“CPU负载平均值”,系统将报告0.37(根据mpstat的摘要推断),这仅适用于CPU资源,但隐藏了一个事实,即需要超过一个线程的工作。

我希望这个例子能说明这些数字确实意味着一些深思熟虑的事情(CPU+不可中断),你可以分解它们并找出答案。

理解Linux负载平均值

操作系统伴随着我长大,平均负载意味着平均CPU负载,所以Linux版本一直困扰着我。也许真正的问题一直以来都是“负载平均值”这个词和“I/O”一样模棱两可。哪种类型的I/O?磁盘I/O?文件系统I/O?网络I/O。。。同样,平均负荷是多少?CPU平均负载?系统平均负载?通过这种方式澄清,我可以这样理解:

  • 在Linux上,负载平均值是“系统负载平均值”,用于衡量整个系统正在工作和等待工作的线程数(CPU、磁盘、不可中断锁)。换句话说,它度量的是不是完全空闲的线程数。优势:包括对不同资源的需求。
  • 在其他操作系统上,负载平均值是“CPU负载平均值”,用于测量CPU运行+CPU可运行线程的数量。优点:易于理解和推理(仅适用于CPU)。

请注意,还有另一种可能的类型:“物理资源负载平均值”,它只包括物理资源的负载(CPU+磁盘)。
也许有一天我们会在Linux中添加额外的平均负载,让用户选择他们想要使用的:一个单独的“CPU平均负载”、“磁盘平均负载”、“网络平均负载”等等,或者只使用不同的指标。

什么是“好”或“坏”平均负载?

有些人发现了一些似乎适用于他们的系统和工作负载的值:他们知道当负载超过X时,应用程序延迟很高,客户开始抱怨。但这并没有真正的规则。

使用CPU负载平均值,可以将该值除以CPU核心数,然后说,如果该比率超过1.0,则你正在饱和运行,这可能会导致性能问题。这有点含糊不清,因为它是一个长期平均值(至少一分钟),可以隐藏变化。一个比率为1.5的系统可能运行良好,而另一个比率为1.5的系统可能在几分钟内表现糟糕。

我曾经管理过一个双CPU的电子邮件服务器,该服务器白天的平均CPU负载在11到16之间(比率在5.5到8之间)。延迟是可以接受的,没有人抱怨。这是一个极端的例子:大多数系统的负载/CPU比率只有2。

至于Linux的系统负载平均值:这些平均值甚至更加模糊,因为它们涵盖了不同的资源类型,所以不能只除以CPU核心数。这对于相对比较更有用:如果你知道系统在负载为20时运行良好,而现在是40时,那么是时候深入研究其他指标了,看看发生了什么。

更好的指标

当Linux平均负载增加时,你知道对资源(CPU、磁盘和一些锁)的需求会增加,但不确定是哪个。你可以使用其他指标进行澄清。例如,对于CPU:

  • 每CPU利用率:例如,使用 mpstat -P ALL 1
  • 每进程CPU利用率:例如,toppidstat 1 等。
  • 每线程运行队列(调度程序)延迟:例如,在/proc/PID/schedstatsdelaystatsperf sched
  • CPU运行队列延迟:例如,在/proc/schedstatperf sched、我的 runqlat bcc 工具中。
  • CPU运行队列长度:例如,使用vmstat 1和’r’列,或我的runqlen bcc工具。

前两个是利用率指标,后三个是饱和指标。利用率指标有助于描述工作负载,饱和指标有助于识别性能问题。最佳CPU饱和指标是运行队列(或调度程序)延迟的度量:任务/线程处于可运行状态但必须等待轮到它的时间。这些允许你确定性能问题的严重程度,例如,线程在调度程序延迟中花费的时间百分比。相反,测量运行队列长度可能表明存在问题,但更难估计其大小。

schedstats工具在Linux4.6(sysctl kernel.sched_schedstats)中被设置为可调内核,并在默认情况下更改为关闭。延迟计费公开了相同的调度程序延迟度量,它在 cpustat 中,我只是建议将它也添加到 htop 中,因为这将使人们更容易使用。比从(未记录)/proc/sched_调试输出中删除等待时间(调度程序延迟)指标更容易:

$ awk 'NF > 7 { if ($1 == "task") { if (h == 0) { print; h=1 } } else { print } }' /proc/sched_debug
            task   PID         tree-key  switches  prio     wait-time             sum-exec        sum-sleep
         systemd     1      5028.684564    306666   120        43.133899     48840.448980   2106893.162610 0 0 /init.scope
     ksoftirqd/0     3 99071232057.573051   1109494   120         5.682347     21846.967164   2096704.183312 0 0 /
    kworker/0:0H     5 99062732253.878471         9   100         0.014976         0.037737         0.000000 0 0 /
     migration/0     9         0.000000   1995690     0         0.000000     25020.580993         0.000000 0 0 /
   lru-add-drain    10        28.548203         2   100         0.000000         0.002620         0.000000 0 0 /
      watchdog/0    11         0.000000   3368570     0         0.000000     23989.957382         0.000000 0 0 /
         cpuhp/0    12      1216.569504         6   120         0.000000         0.010958         0.000000 0 0 /
          xenbus    58  72026342.961752       343   120         0.000000         1.471102         0.000000 0 0 /
      khungtaskd    59 99071124375.968195    111514   120         0.048912      5708.875023   2054143.190593 0 0 /
[...]
         dockerd 16014    247832.821522   2020884   120        95.016057    131987.990617   2298828.078531 0 0 /system.slice/docker.service
         dockerd 16015    106611.777737   2961407   120         0.000000    160704.014444         0.000000 0 0 /system.slice/docker.service
         dockerd 16024       101.600644        16   120         0.000000         0.915798         0.000000 0 0 /system.slice/
[...]

除了CPU指标外,你还可以查找磁盘设备的利用率和饱和指标。我将重点放在这些指标(使用方法),并有一个 Linux清单

虽然有更明确的指标,但这并不意味着平均负载是无用的。它与其他指标一起成功地用于云计算微服务的扩展策略。这有助于微服务对不同类型的负载增加、CPU或磁盘I/O做出响应。有了这些策略,在扩展时出错(花费金钱)比不扩展(流失客户)更安全,因而需要参考更多指标。如果我们扩展太多,我们会在第二天调试为什么。

我一直使用负载平均值的一个原因是它们的历史信息。如果我被要求检查云上一个性能差的实例,然后登录并发现一分钟的平均值远低于十五分钟的平均值,这是一个很大的线索,我可能太晚了,无法实时看到性能问题。但在转向其他指标之前,我只花了几秒钟考虑平均负载。

结论

1993年,一位Linux工程师发现了一个负载平均值的非直观情况,并使用三行补丁将其从“CPU负载平均值”永久更改为人们可能称之为“系统负载平均值”。他的更改包括处于不可中断状态的任务,因此负载平均值反映了对磁盘资源的需求,而不仅仅是CPU。这些系统负载平均数统计正在工作和等待工作的线程数,并总结为指数衰减移动和的平均数的三元组,使用1、5和15分钟作为等式中的常数。这个三元组的数字让你看到负载是增加还是减少,它们的最大值可能是用于与它们自身的相对比较。

不可中断状态的使用在Linux内核中得到了发展,现在包括不可中断锁原语。如果平均负载是运行和等待线程(而不是严格意义上需要硬件资源的线程)的需求度量,那么它们仍然按照我们希望的方式工作。

在这篇文章中,我找到了1993年的Linux负载平均补丁——这是一个出人意料的难以找到的补丁——包含了作者最初的解释。我还使用bcc/eBPF在现代Linux系统上测量了不可中断状态下的堆栈跟踪和时间,并将此时间可视化为 off-CPU火焰图。此可视化提供了许多不可中断睡眠的示例,可以在需要时生成,以解释异常高的平均负载。我还提出了其他指标,你可以使用这些指标来更详细地了解系统负载,而不是平均负载。

最后,我将引用Linux源代码中kernel/sched/loadavg.c顶部调度程序维护人员Peter Zijlstra的一条评论:

这个文件包含计算全局loadavg数字所需的魔法位。这是一个愚蠢的数字,但人们认为它很重要。我们费了很大的劲才让它在大机器和tickless内核上工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值