平均负载高但 CPU 使用率和磁盘 I/O 低

平均负载高但 CPU 使用率和磁盘 I/O 低

我的一台服务器上遇到了一个奇怪的问题。这是一台拥有一个专用 CPU 核心的 KVM VPS。

有时负载会飙升至 2.0 左右: 负荷图

但是,在此期间 CPU 使用率实际上并没有增加,这也排除了 iowait 是原因: CPU 使用率图表

这种情况似乎具有周期性(例如,在这张图中,大约每 20-25 分钟发生一次)。我怀疑是 cronjob,但我没有每 20 分钟运行一次的 cronjob。我也尝试过禁用 cronjob,但负载峰值仍然会出现。

我在通过 SSH 进入服务器时确实看到了这种情况的发生……负载为 1.88,但 CPU 有 94% 处于空闲状态,iowait 为 0%(我预计这可能是原因)

<code>top</code> 输出 <code>htop</code> 输出

当这种情况发生时,似乎没有大量的磁盘 I/O。

我被难住了。有什么想法吗?

答案1

所以我解决了这个问题...结果发现这是由我用来监控服务器的软件(Netdata)引起的。

Linux 每 5 秒更新一次平均负载。事实上,它每 5 秒加一个“滴答”更新一次

sched/loadavg.h

#define LOAD_FREQ   (5*HZ+1) /* 5 sec intervals */

sched/loadavg.c

 * The global load average is an exponentially decaying average of nr_running +
 * nr_uninterruptible.
 *
 * Once every LOAD_FREQ:
 *
 *   nr_active = 0;
 *   for_each_possible_cpu(cpu)
 *  nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
 *
 *   avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)

HZ是内核定时器频率,在编译内核时定义。在我的系统上,它是250

% grep "CONFIG_HZ=" /boot/config-$(uname -r)
CONFIG_HZ=250

这意味着每 5.004 秒(5 + 1/250),Linux 就会计算一次平均负载。它会检查有多少进程正在运行,有多少进程处于不可中断的等待状态(例如等待磁盘 IO),然后使用它来计算平均负载,并随着时间的推移以指数方式平滑它。

假设您有一个每秒启动一堆子进程的进程。例如,Netdata 从某些应用程序收集数据。通常,该过程会非常快,并且不会与平均负载检查重叠,因此一切都很好。但是,每 1251 秒(5.004 * 250),平均负载更新间隔将是 1 秒的精确倍数(即,1251 是 5.004 和 1 的最小公倍数)。1251 秒是 20.85 分钟,这正是我看到平均负载增加的间隔。我的有根据的猜测是,每 20.85 分钟,Linux 都会在启动几个进程并排队运行的确切时间检查平均负载。

我通过禁用 netdata 并手动观察平均负载来确认这一点:

while true; do uptime; sleep 5; done

一个半小时后,我没看到任何类似的尖峰。尖峰仅有的在 Netdata 运行时发生。

所以……最后……我用来监控负载的应用程序是造成这种情况的罪魁祸首。讽刺。他可以救别人一命,却救不了自己。

事实证明,其他人过去也遇到过类似的问题,尽管间隔不同。以下帖子非常有帮助:

在此向 Netdata 开发人员报告:https://github.com/netdata/netdata/issues/5234。最后,我不确定我是否会将其称为错误,但也许 netdata 可以实现一些抖动,这样它就不会每秒都精确地执行一次检查。

相关内容