CPU飆高,系統性能問題如何排查?

簡介: 壓測時或多或少都收到過CPU或者Load高的告警,若是是單機偶發性的,常常會認爲是「宿主機搶佔致使的」,那事實是否真是如此呢?是什麼引發了這些指標的飆高?網絡、磁盤仍是高併發?有什麼工具能夠定位?TOP、PS仍是vmstat?CPU高&Load高和CPU低&Load高,不一樣的表徵又表明着什麼?html

image.png
image.png

一 背景知識

LINUX進程狀態

LINUX 2.6之後的內核中,進程通常存在7種基礎狀態:D-不可中斷睡眠、R-可執行、S-可中斷睡眠、T-暫停態、t-跟蹤態、X-死亡態、Z-殭屍態,這幾種狀態在PS命令中有對應解釋。linux

image.png

  • 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使用率是最直觀的兩個指標,那麼這兩個指標是怎麼被計算出來的呢?是否能互相等價呢?ios

Load Average網絡

很多人都認爲,Load表明正在CPU上運行&等待運行的進程數,即併發

image.png

但Linux系統中,這種描述並不徹底準確。負載均衡

如下爲Linux內核源碼中Load Average計算方法,能夠看出來,所以除了可執行態進程,不可中斷睡眠態進程也會被一塊兒歸入計算,即:異步

image.png

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負載)。socket

CPU使用率tcp

CPU的時間分片通常可分爲4大類:用戶進程運行時間 - User Time, 系統內核運行時間 - System Time, 空閒時間 - Idle Time, 被搶佔時間 - Steal Time。除了Idle Time外,其他時間CPU都處於工做運行狀態。高併發

image.png

一般而言,咱們泛指的總體CPU使用率爲User Time 和 Systime佔比之和(例如tsar中CPU util),即:

image.png

爲了便於定位問題,大多數性能統計工具都將這4類時間片進一步細化成了8類,以下爲TOP對CPU時間片的分類。

image.png

  • us:用戶進程空間中未改變過優先級的進程佔用CPU百分比
  • sy:內核空間佔用CPU百分比
  • ni:用戶進程空間內改變過優先級的進程佔用CPU百分比
  • id:空閒時間百分比
  • wa:空閒&等待I/O的時間百分比
  • hi:硬中斷時間百分比
  • si:軟中斷時間百分比
  • st:虛擬化時被其他VM竊取時間百分比

這8類分片中,除wa和id外,其他分片CPU都處於工做態。

二 資源&瓶頸分析

從上文咱們瞭解到,Load Average和CPU使用率可被細分爲不一樣的子域指標,指向不一樣的資源瓶頸。整體來講,指標與資源瓶頸的對應關係基本以下圖所示。

image.png

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致使。

三 排查策略

利用現有經常使用的工具,咱們經常使用的排查策略基本以下圖所示:

image.png

從問題發現到最終定位,基本可分爲四個階段:

資源瓶頸定位

這一階段經過全局性能檢測工具,初步定位資源消耗異常位點。

經常使用的工具備:

  • 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

相關文章
相關標籤/搜索