因此,我最近在两台服务器上遇到了一个奇怪的问题。我注意到平均负载大约每20分钟增加一次:
我怀疑是cronjob,但我没有每20分钟运行一次的cronjob。此外,在此期间,CPU使用率实际上并没有增加:
我做了一些挖掘,花了很长时间才弄清正在发生的事情。
那么,什么是平均负载?
“平均负载”是一个术语,用于描述系统“繁忙”程度的度量。类似Unix的系统(包括Linux)显示的平均负载为三个数字,分别表示前一分钟,五分钟和十五分钟的系统负载。这些数字表示当前正在使用CPU,正在等待使用CPU或正在等待磁盘I / O的进程数。维基百科文章有更多详细信息。
Linux每5秒更新一次平均负载。实际上,它实际上每5秒更新一次,并加上一个“滴答”。这样做的原因是为了避免与其他五秒计时器同时出现:
事实证明,内核中还有其他五秒钟的计时器,如果这些计时器同步,则负载平均会因恰巧同时发生的事件而人为地夸大。因此,只需按计时器刻度线来抵消平均负载计算即可。
从Linux内核代码:
sched / loadavg.h:
1个 2 | #define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */ |
sched / loadavg.c
1个 2 3 4 5 6 7 8 9 10 11 | * 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:
1个 2 3 | % grep "CONFIG_HZ=" /boot/config-$(uname -r) CONFIG_HZ=250 |
这意味着Linux每5.004秒(5 + 1/250)计算一次平均负载。它检查有多少个进程正在活动运行,以及有多少个进程处于不间断的等待状态(例如,等待磁盘IO),并使用它来计算平均负载,并随时间按指数方式平滑负载平均。
假设您有一个每秒启动一堆子流程的流程。例如,Netdata从某些应用程序收集数据。通常,此过程将非常快,并且不会与平均负载检查重叠,因此一切正常。但是,每1251秒(5.004 * 250),负载平均更新间隔将是一秒的精确倍数(即1251是5.004和1的最小公倍数)。1251秒是20.85分钟,恰好是我看到平均负载增加的时间间隔。我的推测是,每20.85分钟,Linux就会在启动多个进程并使其在队列中运行的确切时间检查平均负载。
我通过禁用netdata并手动查看平均负载来确认这一点:
1个 2 | while true; do uptime; sleep 5; done |
1.5小时后,我没有看到任何类似的峰值。尖峰仅在运行Netdata时发生。
事实证明,尽管间隔不同,其他人过去也遇到过类似的问题。