CPU飙高,系统性能问题如何排查?
压测时或多或少都收到过CPU或者Load高的高系告警,如果是统性题何单机偶发性的,经常会认为是排查“宿主机抢占导致的”,那事实是高系否真是如此呢?是什么引起了这些指标的飙高?网络、磁盘还是统性题何高并发?有什么工具可以定位?TOP、PS还是排查vmstat?CPU高&Load高和CPU低&Load高,不同的高系表征又代表着什么?
一 背景知识
LINUX进程状态
LINUX 2.6以后的内核中,进程一般存在7种基础状态:D-不可中断睡眠、统性题何R-可执行、排查S-可中断睡眠、高系T-暂停态、统性题何t-跟踪态、排查X-死亡态、高系Z-僵尸态,统性题何这几种状态在PS命令中有对应解释。排查
Load Average & CPU使用率
谈到系统性能,Load和CPU使用率是最直观的两个指标,那么这两个指标是怎么被计算出来的呢?是否能互相等价呢?
Load Average
不少人都认为,Load代表正在CPU上运行&等待运行的进程数,即
但Linux系统中,这种描述并不完全准确。
以下为Linux内核源码中Load Average计算方法,可以看出来,因此除了可执行态进程,不可中断睡眠态进程也会被一起纳入计算,即:
在前文 Linux进程状态 中有提到过,不可中断睡眠态的进程(TASK_UNINTERRUTED)一般都在进行I/O等待,比如磁盘、网络或者其他外设等待。由此我们可以看出,Load Average在Linux中体现的是整体系统负载,即CPU负载 + Disk负载 + 网络负载 + 其余外设负载,并不能完全等同于CPU使用率(这种情况只出现在Linux中,其余系统比如Unix,Load还是只代表CPU负载)。
CPU使用率
CPU的时间分片一般可分为4大类:用户进程运行时间 - User Time, 系统内核运行时间 - System Time, 空闲时间 - Idle Time, 被抢占时间 - Steal Time。除了Idle Time外,其余时间CPU都处于工作运行状态。
通常而言,我们泛指的整体CPU使用率为User Time 和 Systime占比之和(例如tsar中CPU util),即:
为了便于定位问题,大多数性能统计工具都将这4类时间片进一步细化成了8类,如下为TOP对CPU时间片的分类。
这8类分片中,除wa和id外,其余分片CPU都处于工作态。
二 资源&瓶颈分析
从上文我们了解到,Load Average和CPU使用率可被细分为不同的子域指标,指向不同的资源瓶颈。总体来说,指标与资源瓶颈的对应关系基本如下图所示。
Load高 & CPU高
这是我们最常遇到的一类情况,即load上涨是CPU负载上升导致。根据CPU具体资源分配表现,可分为以下几类:
CPU sys高
这种情况CPU主要开销在于系统内核,可进一步查看上下文切换情况。
如果非自愿上下文切换较多,说明CPU抢占较为激烈,大量进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。 如果自愿上下文切换较多,说明可能存在I/O、内存等系统资源瓶颈,大量进程无法获取所需资源,导致的上下文切换。CPU si高
这种情况CPU大量消耗在软中断,可进一步查看软中断类型。一般而言,网络I/O或者线程调度引起软中断最为常见:
NET_TX & NET_RX。NET_TX是发送网络数据包的软中断,NET_RX是接收网络数据包的软中断,这两种类型的软中断较高时,系统存在网络I/O瓶颈可能性较大。 SCHED。SCHED为进程调度以及负载均衡引起的中断,这种中断出现较多时,系统存在较多进程切换,一般与非自愿上下文切换高同时出现,可能存在CPU瓶颈。CPU us高
这种情况说明资源主要消耗在应用进程,可能引发的原因有以下几类:
死循环或代码中存在CPU密集计算。这种情况多核CPU us会同时上涨。 内存问题,导致大量FULLGC,阻塞线程。这种情况一般只有一核CPU us上涨。 资源等待造成线程池满,连带引发CPU上涨。这种情况下,线程池满等异常会同时出现。Load高 & CPU低
这种情况出现的根本原因在于不可中断睡眠态(TASK_UNINTERRUPTIBLE)进程数较多,即CPU负载不高,但I/O负载较高。可进一步定位是磁盘I/O还是网络I/O导致。
三 排查策略
利用现有常用的工具,我们常用的排查策略基本如下图所示:
从问题发现到最终定位,基本可分为四个阶段:
资源瓶颈定位
这一阶段通过全局性能检测工具,初步定位资源消耗异常位点。
常用的工具有:
top、vmstat、tsar(历史) 中断:/proc/softirqs、/proc/interrupts I/O:iostat、dstat热点进程定位
定位到资源瓶颈后,可进一步分析具体进程资源消耗情况,找到热点进程。
常用工具有:
上下文切换:pidstat -w CPU:pidstat -u I/O:iotop、pidstat -d 僵尸进程:ps线程&进程内部资源定位
找到具体进程后,可细化分析进程内部资源开销情况。
常用工具有:
上下文切换:pidstat -w -p [pid] CPU:pidstat -u -p [pid] I/O: lsof热点事件&方法分析
获取到热点线程后,我们可用trace或者dump工具,将线程反向关联,将问题范围定位到具体方法&堆栈。
常用的工具有:
perf:Linux自带性能分析工具,功能类似hotmethod,基于事件采样原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析。 jstack 结合ps -Lp或者pidstat -p一起使用,可初步定位热点线程。 结合zprofile-threaddump一起使用,可统计线程分布、等锁情况,常用与线程数增加分析。 strace:跟踪进程执行时的系统调用和所接收的信号。 tcpdump:抓包分析,常用于网络I/O瓶颈定位。相关阅读
[1]Linux Load Averages: Solving the Mystery
http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html
[2]What exactly is a load average?
http://linuxtechsupport.blogspot.com/2008/10/what-exactly-is-load-average.html