1. 程式人生 > >伺服器效能指標(二)——CPU利用率分析及問題排查

伺服器效能指標(二)——CPU利用率分析及問題排查

平常的工作中,在衡量伺服器的效能時,經常會涉及到幾個指標,load、cpu、mem、qps、rt等。每個指標都有其獨特的意義,很多時候在線上出現問題時,往往會伴隨著某些指標的異常。大部分情況下,在問題發生之前,某些指標就會提前有異常顯示。

上一篇文章中,我們介紹了一個重要的指標就是負載(Load),其中我們提到Linux的負載高,主要是由於CPU使用、記憶體使用、IO消耗三部分構成。任意一項使用過多,都將導致伺服器負載的急劇攀升。本文就來分析其中的第二項,CPU的利用率。主要涉及CPU利用率的定義、檢視CPU利用率方式、CPU利用率飆高排查思路等。

什麼是CPU利用率

CPU利用率,又稱CPU使用率。顧名思義,CPU利用率是來描述CPU的使用情況的,表明了一段時間內CPU被佔用的情況。使用率越高,說明你的機器在這個時間上運行了很多程式,反之較少。使用率的高低與你的CPU強弱有直接關係。

在接下來深入介紹CPU的利用率之前,我們先來解釋一個簡單的概念,可能是很多人一直存在誤解的地方。

很多人都知道,現在我們用到作業系統,無論是Windows、Linux還是MacOS等其實都是多使用者多工分時作業系統。使用這些作業系統的使用者是可以“同時”幹多件事的,這已經是日常習慣了,並沒覺得有什麼特別。 但是實際上,對於單CPU的計算機來說,在CPU中,同一時間是隻能幹一件事兒的。為了看起來像是“同時幹多件事”,分時作業系統是把CPU的時間劃分成長短基本相同的時間區間,即"時間片",通過作業系統的管理,把這些時間片依次輪流地分配給各個使用者使用。 如果某個作業在時間片結束之前,整個任務還沒有完成,那麼該作業就被暫停下來,放棄CPU,等待下一輪迴圈再繼續做.此時CPU又分配給另一個作業去使用。 由於計算機的處理速度很快,只要時間片的間隔取得適當,那麼一個使用者作業從用完分配給它的一個時間片到獲得下一個CPU時間片,中間有所"停頓",但使用者察覺不出來,好像整個系統全由它"獨佔"似的。

而我們說到的CPU的佔用率,一般指的就是對時間片的佔用情況。

檢視CPU利用率

在上一篇文章中,我們介紹過,使用uptimetopw等命令可以在Linux檢視系統的負載情況。其中,top命令也可以用來檢視CPU的利用率,除此之外,還可以使用vmstat來檢視cpu的利用率。

vmstat命令

vmstat命令是最常見的Linux/Unix監控工具,可以展現給定時間間隔的伺服器的狀態值,包括伺服器的CPU使用率,記憶體使用,虛擬記憶體交換情況,IO讀寫情況。

1➜  ~ vmstat
2procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
3 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
4 0  1      0 2446260      0 3202312    0    0   201 16304    1    6  0  0 84  5 1

從上面的結果中我們可以看到很多資訊,我們本文重點關注下cpu部分的指標。

1us sy id wa st
20  0  84  5 1

以上幾個指標是當前CPU的佔用情況。

%us:使用者程序執行時間百分比

us的值比較高時,說明使用者程序消耗的CPU時間多,但是如果長期超50%的使用,那麼我們就該考慮優化程式演算法或者進行加速。

%sy:核心系統程序執行時間百分比

sy的值高時,說明系統核心消耗的CPU資源多,這並不是良性表現,我們應該檢查原因。

%id:空閒時間百分比

%wa:IO等待時間百分比

wa的值高時,說明IO等待比較嚴重,這可能由於磁碟大量作隨機訪問造成,也有可能磁碟出現瓶頸(塊操作)。

%st:虛擬 CPU 等待實際 CPU 的時間的百分比

一般vmstat工具的使用是通過兩個數字引數來完成的,第一個引數是取樣的時間間隔數,單位是秒,第二個引數是取樣的次數。

1➜  ~ vmstat 2 2
2procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
3 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
4 0  0      0 2479444      0 3165172    0    0   196 15905    2    8  0  0 84  5 11
5 0  0      0 2479404      0 3165176    0    0     0  2804 81664 2715  0  0 90  1  9

以上命令表示採集兩次資料,每隔2秒採集一次。

top命令

top命令是Linux下常用的效能分析工具,能夠實時顯示系統中各個程序的資源佔用狀況,類似於Windows的工作管理員。

1~ top
2top - 10:58:07 up 18:13,  1 user,  load average: 0.32, 0.24, 0.19
3Tasks:  64 total,   1 running,  63 sleeping,   0 stopped,   0 zombie
4Cpu(s):  0.1%us,  0.2%sy,  0.0%ni, 92.8%id,  0.1%wa,  0.0%hi,  0.0%si,  6.8%st
5Mem:   8388608k total,  5928076k used,  2460532k free,        0k buffers
6Swap: 16777216k total,        0k used, 16777216k free,  3181996k cached
7   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
8  2393 admin     20   0 5056m 2.2g  56m S  4.3 27.6  79:06.21 java
9  1054 root      20   0  338m 9760 5112 S  0.3  0.1   2:37.30 logagent

使用top命令,除了可以檢視Load Avg以外,還可以顯示CPU利用率資訊。

以上top命令列印的資訊中(Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 92.8%id, 0.1%wa, 0.0%hi, 0.0%si, 6.8%st),第三行反映了當前cpu的整體情況。

從上面的列印資訊中我們還可以看到,ID為2393的java程序當前記憶體使用率最高,佔到4.3%左右。

由於Java是多執行緒的,所有,有些時候我們希望可以檢視一個Java程序中所有執行緒的cpu使用率如何,也可以使用top命令來檢視。

1➜  ~ top -Hp 1893
2PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
319163 admin     20   0 5056m 2.2g  56m S  1.7 27.6  17:39.97 java
410649 admin     20   0 5056m 2.2g  56m S  0.7 27.6   4:07.64 java
55884 admin     20   0 5056m 2.2g  56m S  0.3 27.6   2:18.19 java
610650 admin     20   0 5056m 2.2g  56m S  0.3 27.6   1:24.77 java

通過top -Hp 1893命令,我們可以發現,當前1893這個程序中,ID為19163的執行緒佔用CPU最高,達到1.7%左右。

PS:top命令的輸出結果是動態的,隨著系統的情況實時變化的。

CPU使用率的計算邏輯

描述系統cpu使用情況主要有一下幾點:

user 從系統啟動到現在,CPU處於使用者態的執行時間。不包含nice值為負的程序。

nice 從系統啟動到現在,CPUnice為負值的程序佔用的cpu時間。

system 從系統啟動到現在,CPU處於核心態的執行時間。

idle 從系統啟動到現在,CPU除了 iowait外的等待時間。

iowait 從系統啟動到現在,CPUio 等待時間。

irq 從系統啟動到現在,CPU硬中斷花費的時間。

softirq 從系統啟動到現在,CPU軟中斷花費的時間。

steal 從系統啟動到現在,CPU執行其他虛擬環境中的作業系統花費的時間。

guest 從系統啟動到現在,CPU執行在通過Linux核心控制的客戶作業系統上的虛擬cpu的時間。

guest_nice 從系統啟動到現在,CPU執行在通過Linux核心控制的客戶作業系統上的虛擬cpu的時間, nice 為負值程序。

知道了以上引數的意思,計算某段時間內的cpu使用率就不難,由於cpu資源是在高速的變化,於是計算cpu使用率只能是在一段時間內的,設定兩個時間點為t1和t2, CPU在t1和t2時間內總的使用時間:

1( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2 + steal2 + guest2 + guest_nice2 ) - ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1 + steal1 + guest1 + guest_nice1)

CPU的空閒時間:

1(idle2 -idle1)

CPU在t1和t2時間內的使用率

1CPU非空閒時間/CPU總時間*100%=(1-CPU的空閒時間/CPU總時間)*100%

則:

1CPU(t1,t2)使用率:1-(idle2-idle1)/(( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2 + steal2 + guest2 + guest_nice2 ) - ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1 + steal1 + guest1 + guest_nice1))

(參考資料:https://blog.csdn.net/IT_DREAM_ER/article/details/52037368)

CPU利用率和負載

我們上一篇文章介紹了系統的負載,本文介紹了CPU利用率,很多小夥伴就會分不清楚了,這兩者之前到底有什麼區別和聯絡呢?

CPU利用率是對一個時間段內CPU使用狀況的統計,通過這個指標可以看出在某一個時間段內CPU被佔用的情況。

CPU負載是在一段時間內CPU正在處理以及等待CPU處理的程序數之和的統計資訊,也就是CPU使用佇列的長度的統計資訊。

有一個很好的比喻,就是把CPU的使用比喻成排隊打電話:

我們將CPU就類比為電話亭,每一個程序都是一個需要打電話的人。現在有一個電話亭(單核計算機),有10個人需要打電話(10個程序)。現在使用電話的規則是管理員會按照順序給每一個人輪流分配1分鐘的使用電話時間,如果使用者在1分鐘內使用完畢,那麼可以將電話使用權返還給管理員,如果到了1分鐘電話使用者還沒有使用完畢,那麼需要重新排隊,等待再次分配使用。在電話亭使用過程中,肯定會有人打完電話走掉,有人沒有打完電話而選擇重新排隊,同樣也會有新來的人繼續排隊,這個人數的變化就相當於任務數的增減。

CPU的Load統計一定時間段內,所有使用電話的人加上等待電話分配的人數的平均值。為了統計平均負載情況,我們5分鐘統計一次人數,並在第1、5、15分鐘的時候對統計情況取平均值,從而形成第1、5、15分鐘的平均負載。

CPU利用率統計的程序在進入電話亭後,真正使用電話的時間和在電話亭停留的時間的比值。例如一個使用者得到了一分鐘的使用權,在10秒鐘內打了電話,然後去查詢號碼本花了20秒鐘,再用剩下的30秒打了另一個電話。那麼他的利用率就是(10+30)/60

Java Web應用CPU使用率飆高排查思路

當發現系統的CPU使用率飆高時,首先要定位到是哪個程序佔用的CPU較高。一般情況下,對於Java程式碼來說,導致CPU飆高可能由以下幾個原因引起:

1、記憶體洩露、導致大量Full GC(如典型的Java 1.7之前的String.subString導致的記憶體洩露問題) 2、程式碼存在死迴圈(如典型的多執行緒場景使用HashMap導致死迴圈的問題)

這部分問題排查思路其實和我上一篇問文章的思路差不多,基本都是先定位到佔用CPU較多的程序和執行緒,然後通過命令在檢視這條執行緒執行情況。通過分析程式碼來定位其中的問題。

這裡就不重複介紹了,最重要的是熟練的使用jstackjstat以及jmap等命令來定位及解決Java程序的問題。