关于cpu:CPU飙高系统性能问题如何排查

5次阅读

共计 4061 个字符,预计需要花费 11 分钟才能阅读完成。

简介: 压测时或多或少都收到过 CPU 或者 Load 高的告警,如果是单机偶发性的,常常会认为是“宿主机抢占导致的”,那事实是否真是如此呢?是什么引起了这些指标的飙高?网络、磁盘还是高并发?有什么工具能够定位?TOP、PS 还是 vmstat?CPU 高 &Load 高和 CPU 低 &Load 高,不同的表征又代表着什么?


一 背景常识

LINUX 过程状态

LINUX 2.6 当前的内核中,过程个别存在 7 种根底状态:D- 不可中断睡眠、R- 可执行、S- 可中断睡眠、T- 暂停态、t- 跟踪态、X- 死亡态、Z- 僵尸态,这几种状态在 PS 命令中有对应解释。

  • D (TASK_UNINTERRUPTIBLE),不可中断睡眠态。顾名思义,位于这种状态的过程处于睡眠中,并且不容许被其余过程或中断 (异步信号) 打断。因而这种状态的过程,是无奈应用 kill - 9 杀死的 (kill 也是一种信号),除非重启零碎(没错,就是这么头硬)。不过这种状态个别由 I / O 期待(比方磁盘 I /O、网络 I /O、外设 I / O 等) 引起,呈现工夫十分短暂,大多很难被 PS 或者 TOP 命令捕捉(除非 I /O HANG 死)。SLEEP 态过程不会占用任何 CPU 资源。
  • R (TASK_RUNNING),可执行态。这种状态的过程都位于 CPU 的可执行队列中,正在运行或者正在期待运行,即不是在下班就是在下班的路上。
  • S (TASK_INTERRUPTIBLE),可中断睡眠态。不同于 D,这种状态的过程尽管也处于睡眠中,然而是容许被中断的。这种过程个别在期待某事件的产生(比方 socket 连贯、信号量等),而被挂起。一旦这些工夫实现,过程将被唤醒转为 R 态。如果不在高负载期间,零碎中大部分过程都处于 S 态。SLEEP 态过程不会占用任何 CPU 资源。
  • T&t (__TASK_STOPPED & __TASK_TRACED),暂停 or 跟踪态。这种两种状态的过程都处于运行进行的状态。不同之处是暂停态个别因为收到 SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOUT 四种信号被进行,而跟踪态是因为过程被另一个过程跟踪引起(比方 gdb 断点)。暂停态过程会开释所有占用资源。
  • Z (EXIT_ZOMBIE), 僵尸态。这种状态的过程实际上曾经完结了,然而父过程还没有回收它的资源(比方过程的描述符、PID 等)。僵尸态过程会开释除过程入口之外的所有资源。
  • X (EXIT_DEAD), 死亡态。过程的真正完结态,这种状态个别在失常零碎中捕捉不到。

Load Average & CPU 使用率

谈到零碎性能,Load 和 CPU 使用率是最直观的两个指标,那么这两个指标是怎么被计算出来的呢?是否能相互等价呢?

Load Average

不少人都认为,Load 代表正在 CPU 上运行 & 期待运行的过程数,即

但 Linux 零碎中,这种形容并不齐全精确。

以下为 Linux 内核源码中 Load Average 计算方法,能够看进去,因而除了可执行态过程,不可中断睡眠态过程也会被一起纳入计算,即:

602staticunsignedlongcount_active_tasks(void)
603 {
604structtask_struct*p;
605unsignedlongnr=0;
606607read_lock(&tasklist_lock);
608for_each_task(p) {609if ((p->state==TASK_RUNNING610 (p->state&TASK_UNINTERRUPTIBLE)))
611nr+=FIXED_1;
612 }
613read_unlock(&tasklist_lock);
614returnnr;
615 }
......
625staticinlinevoidcalc_load(unsignedlongticks)
626 {
627unsignedlongactive_tasks; /* fixed-point */628staticintcount=LOAD_FREQ;
629630count-=ticks;
631if (count<0) {
632count+=LOAD_FREQ;
633active_tasks=count_active_tasks();
634CALC_LOAD(avenrun[0], EXP_1, active_tasks);
635CALC_LOAD(avenrun[1], EXP_5, active_tasks);
636CALC_LOAD(avenrun[2], EXP_15, active_tasks);
637 }
638 }

在前文 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 工夫片的分类。

  • us:用户过程空间中未扭转过优先级的过程占用 CPU 百分比
  • sy:内核空间占用 CPU 百分比
  • ni:用户过程空间内扭转过优先级的过程占用 CPU 百分比
  • id:闲暇工夫百分比
  • wa:闲暇 & 期待 I / O 的工夫百分比
  • hi:硬中断工夫百分比
  • si:软中断工夫百分比
  • st:虚拟化时被其余 VM 窃取工夫百分比

这 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

正文完
 0