究竟什么是运行队列?
run-queue :活动(正在运行)和排队的进程数。
在第二个示例中,当系统处于活动状态时,我们看到 8 个运行队列,这已经是具有 8 个内核的系统应该运行的最大上限。
当然,运行队列可能会显示像 36 甚至 101 这样的值,如果在前 36 个上我们有 36 个内核,而在第二个 101 上我们有超过 101 个内核,那么它们将非常好。
运行队列列应始终低于/与系统上安装的内核数相同,当然,在只有 8 个内核的系统上可以看到 100 个运行队列,这意味着 CPU 主动为 8 个进程提供服务,其余 92 个进程正在排队等待为执行。
如果运行队列高于已安装的 CPU 内核,则应在检查 APP/DB 性能和缺少调整方面进行调查,或者可以表明系统未正确扩展以服务此类运行队列/负载。
就像负载平均运行队列应该保持在安装的内核数量以下一样,如果不将此值保持在最大阈值以下会导致速度减慢/挂起或者逐出情况(如果系统启用了 HA),因为操作系统可以简单地在磁盘/网络层上排队心跳监控因为它忙于处理其他任务。
高平均负载和运行队列会导致突然崩溃/挂起的情况下,值得通过 3rd 方监控工具主动监控这两个值,并在运行队列/平均负载占用超过 70% 的实际 CPU 资源时发出警报。
负载平均采用的第二个重要列是 vmstat 中的“b”状态,它解释了阻塞状态进程,这可以很容易地解释为状态 D 进程(等待后端 IO 通常完成存储活动)。
如果平均负载很高并且没有进程正在运行,并且 vmstat 显示异常的“b”状态值,那么是时候检查 SAN 性能或者验证任何操作系统组件(如 ISCSI/NFS/NIC/HBA),这些组件可能会遇到一些问题并导致Linux下严重阻塞状态。
例如,NFS 服务器可能在 CPU 级别上很忙,并且所有客户端 (Linux) 进程/任务将在状态 d (b) 中排队,导致“排队”,然后可能会在所有进程都在等待时释放大量运行队列为了让后端 IO 稍后完成,它们可能会再次切换到 Running 状态,从而导致大量运行队列,这可能导致挂起/恐慌状态或者之后导致驱逐情况。
由于高平均负载,网络吞吐量和 TCP/UDP 流量也会受到影响,因为系统将忙于处理其他任务,而不是确认传入/传出连接并通过 NFS/ISCSI 等优先处理传入的网络 IO 流量。
在某些情况下,TOP 可能会出现%CPU 值大于 100 这完全没问题,因为 Linux 中默认的 TOP 命令显示单核操作,因此在多核设置中 %CPU 值可以大于 100%。
例如,如果 PID 充分利用 4 个内核,那么 %CPU 值将显示 400
# top top - 11:49:34 up 25 days, 5:56, 68 users, load average: 0.09, 0.14, 0.46 Tasks: 456 total, 1 running, 445 sleeping, 10 stopped, 0 zombie Cpu(s): 0.8%us, 0.4%sy, 0.0%ni, 98.6%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 141823788k total, 140483388k used, 1340400k free, 313452k buffers Swap: 16772092k total, 0k used, 16772092k free, 134695384k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1438 java 20 0 945m 4220 2528 S 400.5 0.0 56:31.95 java <--
关于 %CPU 的信息:
The task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time. In a true SMP environment, if a process is multi-threaded and top is not operating in Threads mode, amounts greater than 100% may be reported. You toggle Threads mode with the 'H' interactive command.``` 要快速列出正在运行/被阻止的进程,请使用以下 ps 命令: ``` sh # ps r -Af
要列出进程线程以验证父 PID 产生的某些线程是否不会导致 CPU 峰值问题,请执行:
# ps -e -To pid,ppid,state,pcpu,command
或者
# ps -elfL
还要验证操作系统 CPU 是否正在为用户(美国)空间提供服务,请使用以下命令示例:
# sar -P ALL 1 Linux 3.8.13-118.13.3.el6uek.x86_64 (lonitroad) 01/08/2017 _x86_64_ (8 CPU) 02:40:38 PM CPU %user %nice %system %iowait %steal %idle 02:40:39 PM all 12.62 0.00 0.12 6.88 0.00 80.38 02:40:39 PM 0 0.00 0.00 0.00 54.55 0.00 45.45 02:40:39 PM 1 0.00 0.00 0.00 0.00 0.00 100.00 02:40:39 PM 2 0.99 0.00 0.00 0.00 0.00 99.01 02:40:39 PM 3 0.00 0.00 0.00 0.00 0.00 100.00 02:40:39 PM 4 100.00 0.00 0.00 0.00 0.00 0.00 02:40:39 PM 5 0.98 0.00 0.98 0.00 0.00 98.04 02:40:39 PM 6 0.00 0.00 0.00 0.00 0.00 100.00 02:40:39 PM 7 0.00 0.00 0.00 0.00 0.00 100.00 Average: CPU %user %nice %system %iowait %steal %idle Average: all 12.63 0.00 0.13 6.00 0.00 81.24 Average: 0 0.00 0.00 0.00 45.23 0.00 54.77 Average: 1 0.50 0.00 0.00 3.00 0.00 96.50 Average: 2 0.50 0.00 0.00 0.00 0.00 99.50 Average: 3 0.00 0.00 0.00 0.50 0.00 99.50 Average: 4 100.00 0.00 0.00 0.00 0.00 0.00 Average: 5 0.50 0.00 0.50 0.00 0.00 99.00 Average: 6 0.00 0.00 0.00 0.00 0.00 100.00 Average: 7 0.00 0.00 0.00 0.00 0.00 100.00
# mpstat -P ALL Linux 3.8.13-118.13.3.el6uek.x86_64 (onitroad) 01/08/2017 _x86_64_ (8 CPU) 02:41:26 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 02:41:26 PM all 0.79 0.00 0.10 1.18 0.00 0.02 0.00 0.00 97.92 02:41:26 PM 0 0.94 0.00 0.14 2.84 0.00 0.02 0.00 0.00 96.06 02:41:26 PM 1 0.94 0.00 0.14 2.70 0.00 0.02 0.00 0.00 96.20 02:41:26 PM 2 0.93 0.00 0.14 1.13 0.00 0.03 0.00 0.00 97.77 02:41:26 PM 3 0.94 0.00 0.13 2.71 0.00 0.02 0.00 0.00 96.20 02:41:26 PM 4 0.65 0.00 0.06 0.01 0.00 0.01 0.00 0.00 99.28 02:41:26 PM 5 0.65 0.00 0.06 0.01 0.00 0.01 0.00 0.00 99.27 02:41:26 PM 6 0.65 0.00 0.06 0.01 0.00 0.01 0.00 0.00 99.27 02:41:26 PM 7 0.64 0.00 0.05 0.01 0.00 0.01 0.00 0.00 99.29
此外,以下 TOP 命令开关可用于获取 PID 线程信息以及上次为 PID 提供服务的核心:
要在 TOP 中显示线程:
# top -H
要显示上次执行哪个核心服务 PID:
# top
然后按'F'并按'J'并按回车键获得下面的输出,其中'P'行将是最后使用的CPU。
Tasks: 1045 total, 2 running, 1043 sleeping, 0 stopped, 0 zombie Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 93.6%id, 5.9%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 16159656k total, 15349888k used, 809768k free, 597960k buffers Swap: 8232956k total, 218784k used, 8014172k free, 9840192k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ P COMMAND 10428 root 20 0 15228 2228 1724 S 0.7 0.0 0:26.86 2 top 10838 oracle 20 0 4921m 585m 5708 S 0.7 3.7 137:11.13 3 mysqld 15360 root 20 0 15888 2792 1724 R 0.7 0.0 0:00.55 6 top 528 root 20 0 0 0 0 S 0.3 0.0 76:39.23 0 jbd2/dm-0-8 9003 root 20 0 0 0 0 S 0.3 0.0 8:49.33 2 jbd2/dm-3-8 10815 oracle 20 0 4921m 585m 5708 S 0.3 3.7 13:35.18 1 mysqld 14902 oracle 20 0 9431m 2.4g 28m S 0.3 15.5 19:54.77 3 java 15021 oracle 20 0 9431m 2.4g 28m S 0.3 15.5 20:09.19 1 java 15094 oracle 20 0 9431m 2.4g 28m S 0.3 15.5 6:54.88 3 java 32045 enduser 20 0 15228 2220 1724 S 0.3 0.0 9:32.73 5 top 32278 root 20 0 15228 2212 1724 S 0.3 0.0 9:32.96 1 top
在解决 Linux 上的性能问题时,了解各种命令输出(例如 uptime、vmstat)的基础知识非常重要。
在这篇文章中,我们将尝试从 CPU 利用率的角度了解负载平均值和运行队列/阻塞队列。
首先,让我们了解什么是平均负载:
平均负载是运行队列(状态 R)或者等待磁盘 I/O(状态 D)中 1. 5 和 15 分钟的平均作业数。
uptime/top 命令的输出示例:
# uptime 11:49:14 up 25 days, 5:56, 68 users, load average: 0.03, 0.13, 0.47
# top -b -n 1 top - 11:49:34 up 25 days, 5:56, 68 users, load average: 0.09, 0.14, 0.46 Tasks: 456 total, 1 running, 445 sleeping, 10 stopped, 0 zombie Cpu(s): 0.8%us, 0.4%sy, 0.0%ni, 98.6%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 141823788k total, 140483388k used, 1340400k free, 313452k buffers Swap: 16772092k total, 0k used, 16772092k free, 134695384k cached
经验法则是:
- 单核系统 - 如果平均负载为 1.00,则表示系统已被充分利用,如果有更多任务传入,它们将排队等待执行。
- 单核系统 - 如果平均负载为 2.00,则表示系统已经被使用,并且一些任务已经排队等待执行。
- 多核系统(4 核) - 如果平均负载为 1.00,则表示系统使用了其 CPU 能力的 1/4,一项任务正在积极运行,但仍有 3 个核处于“空闲”阶段。
- 多核系统(4 核) - 如果平均负载为 4.00,则表示系统使用了所有 4 核,并表明系统已被充分利用。
在上述情况下是否还有一些余量?
通常否,如果平均负载接近系统操作系统上的内核数,则应审查以查找实际瓶颈和缺少调整,或者操作系统可能无法正确扩展以服务任何 APP/DB 任务。
如何在 Active OS 上计算负载平均值?
为此,我们需要通过 vmstat 命令找到可用的运行队列:
空闲系统(8核系统)
# vmstat 1 6 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 1674516 316588 134364752 0 0 0 1 0 0 1 0 99 0 0 0 0 0 1674624 316588 134364752 0 0 0 0 195 307 0 0 100 0 0 0 0 0 1674624 316596 134364752 0 0 0 12 168 302 0 0 100 0 0 0 0 0 1674624 316596 134364752 0 0 0 0 198 331 0 0 100 0 0 0 0 0 1674624 316596 134364752 0 0 0 0 206 356 0 0 100 0 0 0 0 0 1674624 316600 134364736 0 0 0 12 197 333 0 0 100 0 0
主动系统(8核系统)
# vmstat 1 6 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa st 5 0 0 1674516 316588 134364752 0 0 0 1 0 0 1 0 99 0 0 7 0 0 1674624 316588 134364752 0 0 0 0 195 307 0 0 100 0 0 2 0 0 1674624 316596 134364752 0 0 0 12 168 302 0 0 100 0 0 6 0 0 1674624 316596 134364752 0 0 0 0 198 331 0 0 100 0 0 1 0 0 1674624 316596 134364752 0 0 0 0 206 356 0 0 100 0 0 8 0 0 1674624 316600 134364736 0 0 0 12 197 333 0 0 100 0 0
以上输出是示例,第一个显示当前运行队列 (r) 为 0,其中活动系统运行队列在 6 个探测器中从 1 跳到 8.
常见问题
系统是否应该以上限运行,例如 8 个正在运行的进程,并且在 8 核系统上平均负载具有相同的值?
回答 否
系统应该适当地扩展并且不超过他的可能性的 70% - 所以有一些空间来执行任何新任务 - 这对于启用 HA 的服务器和有任何高端 IO 的系统尤其重要/网络组件可能会被活动操作系统意外排队。
为此,APP/DB 团队应进行深入检查,以验证操作系统下到底运行的是什么。
是否只有 APP/DB 任务导致高运行队列/平均负载
回答 否
某些操作系统任务可能会导致高运行队列或者平均负载,但这些情况非常罕见。
在这种情况下,top 命令将有助于监视 US /SY/NI/ID/WA/HI/SI/ST 值,并关注 SY(系统)部分,该部分表明处理器在内核级别花费了多少时间。
确保它始终低于实际的美国(用户)利用率,并且 SY 不使用,例如,使用 20-30% 的 CPU(取决于 CPU 设置和实际情况)。
例如,高 %SY 可能在高 IO/网络操作期间或者在内存不足情况下可见,示例过程是:kjorunald。
高 %SY 也可能在重系统负载期间可见,例如,高运行队列或者阻塞队列主要由 APP/DB 任务引起,然后观察到 %SY 将在 20-30% 左右,其中 %US 将很多更高。
较高的 %SY 并不总是意味着存在内核或者操作系统问题,例如,可能存在应用程序/数据库代码导致围绕特定内核函数进行许多系统调用以调试此进一步的 strace 或者 perf 应用于验证特定PID 交互。
这是否意味着单核当时只能服务于单进程任务?
回答是/否
CPU 设计用于多任务处理,即使在单核系统中用户仍然可以执行多个任务并在单核设置中启动多个应用程序使用“时间切片”,它允许任务在一定时间内执行,而其他任务将等待执行(这可能每秒发生几次)。
现代系统将利用多核/多线程功能使这种切换影响不那么明显,因此在企业系统上,用户具有多核设置,其中应用程序可以创建更小的线程,从而实现实际的多任务操作(每个核可以服务不同的任务),从而导致更少系统平均负载和较低的任务队列 例如,双核系统可以将应用程序/线程/任务拆分为两个独立的内核,与单核系统相比,内核只切换一半的任务,对系统性能的影响要小得多。