多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 平均负载 ## 如何理解平均负载?--> 平均活跃进程数 * 可运行状态:进程等待或者使用 CPU,ps 中的 R 状态。 * 不可中断状态:正在等待 IO 访问的进程,ps 中的 D 状态,一般指在等待硬件资源。 > 比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。不可中断状态实际上是系统对进程和硬件设备的一种保护机制。 ## 平均负载为多少时合理 经验值是 70%,比较靠谱的做法是看监控趋势。 ## mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标, 以及所有 CPU 的平均指标。 ``` # 显示各个 CPU 的详细信息 mpstat -P ALL 2 5 # 默认显示所有 CPU 的聚合后的信息 mpstat 2 5 ``` ## pidstat 一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及 上下文切换等性能指标 ``` # 显示正在占用 CPU 的进程 pidstat -u 5 1 # -p 可以过滤某个进程 pidstat -u 5 1 -p <pid> ``` >mpstat 和 pidstat 在 sysstat 包中。 --- # CPU 使用率 ## /proc/stat ``` $ cat /proc/stat | grep ^cpu cpu 280580 7407 286084 172900810 83602 0 583 0 0 0 cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0 cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0 ``` user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但 包括了 guest 时间。 nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整 为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优 先级反而越低。 system(通常缩写为 sys),代表内核态 CPU 时间。 idle(通常缩写为 id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)。 iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间。 irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。 softirq(通常缩写为 si),代表处理软中断的 CPU 时间。 steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。 guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚 拟机的 CPU 时间。 guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。 > CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比 > 比如,对比一下 top 和 ps 这两个工具报告的 CPU 使用率,默认的结果很可能不一样,因 为 top 默认使用 3 秒时间间隔,而 ps 使用的却是进程的整个生命周期。 ## perf perf top perf record 和 perf report ``` # -g 显示调用关系 perf top -g -p 1118 ``` ## 无法解释的 CPU 使用率 碰到常规问题无法解释的 CPU 使用率情况时,首先要想到有可能是短时应用导致的问题, 比如有可能是下面这两种情况。 * 第一,应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等 工具也不容易发现。 * 第二,应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU。 对于这类进程,我们可以用 pstree 或者 [execsnoop][1] 找到它们的父进程,再从父进程所在 的应用入手。 # 僵尸进程 # 软中断 事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部: * 上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。 * 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。 ## 取外卖 比如说前面取外卖的例子,上半部就是你接听电话,告诉配送员你已经知道了,其他事儿见面再说,然后电话就可以挂断了;下半部才是取外卖的动作,以及见面后商量发票处理的动作。这样,第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话。 ## 网卡接收数据包 除了取外卖,我再举个最常见的网卡接收数据包的例子,让你更好地理解。网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。 对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。 所以,这两个阶段你也可以这样理解: * 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行; * 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行,异步执行上半部未完成的工作。 Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看/proc/softirqs 来观察软中断的运行情况。 ## SYN FLOOD 导致大量软中断 ``` bash # -S 参数表示设置 TCP 协议的 SYN(同步序列号),-p 表示目的端口为 80 # -i u100 表示每隔 100 微秒发送一个网络帧 # 注:如果你在实践过程中现象不明显,可以尝试把 100 调小,比如调成 10 甚至 1 $ hping3 -S -p 80 -i u100 192.168.0.30 ``` ### 分析过程 系统变慢(ssh 连接,只是网络较慢导致但觉比较慢,但是实际上系统不慢),通过 top 发现软中断很多, SYN FLOOD 导致了大量软中断。 观察到NET_RX软中断在不断变化。 ```bash watch -d cat /proc/softirqs CPU0 CPU1 HI: 0 0 TIMER: 1083906 2368646 NET_TX: 53 9 NET_RX: 1550643 1916776 BLOCK: 0 0 IRQ_POLL: 0 0 TASKLET: 333637 3930 SCHED: 963675 2293171 HRTIMER: 0 0 RCU: 1542111 1590625 ``` sar -n DEV 后的结果计算后发现,每个网络包都很小。 [1]:https://github.com/PoplarYang/perf-tools/blob/master/execsnoop