找到Linux虛機Load高的"元兇"
摘要: 本篇文章從linux load原理角度出發,通過簡單的Linux ps命令編寫腳本,找到虛機內部導致load高的進程。
原文:http://click.aliyun.com/m/42447/
問題描述
有客戶反饋他們的一台ECS周期性地load升高,他們的業務流量並沒有上升,需要我們排查是什麼原因造成的,是否因為底層異常?
要弄清Linux虛機load高,我們要搞清楚Linux top命令中Load的含義。
Load average的值從何而來
在使用top
命令檢查系統負載的時候,可以看到Load averages
欄位,但是這個欄位並不是表示CPU的繁忙程度,而是度量系統整體負載。
Load averages
採樣是從/proc/loadavg
中獲取的:
0.00 0.01 0.05 1/161 29703每個值的含義依次為:
lavg_1 (0.00) 1-分鐘平均負載
lavg_5 (0.01) 5-分鐘平均負載
lavg_15(0.05) 15-分鐘平均負載
nr_running (1) 在採樣時刻,運行隊列的任務的數目,與/proc/stat的procs_running表示相同意思,這個數值是當前可運行的內核調度對象(進程,線程)。
nr_threads (161) 在採樣時刻,系統中活躍的任務的個數(不包括運行已經結束的任務),即這個數值表示當前存在系統中的內核可調度對象的數量。
last_pid(29703) 系統最近創建的進程的PID,包括輕量級進程,即線程。
假設當前有兩個CPU,則每個CPU的當前任務數為0.00/2=0.00
如果你看到load average數值是10,則表明平均有10個進程在運行或等待狀態。有可能系統有很高的負載但是CPU使用率卻很低,或者負載很低而CPU利用率很高,因為這兩者沒有直接關係。
Linux 源碼中關於這一塊的說明:
Load的計算函數:
從這個函數中可以看到,內核計算load採用的是一種平滑移動的演算法,Linux的系統負載指運行隊列的平均長度,需要注意的是:可運行的進程是指處於運行隊列的進程,不是指正在運行的進程。即進程的狀態是TASK_RUNNING或者TASK_UNINTERRUPTIBLE。
Linux內核定義一個長度為3的雙字數組avenrun,雙字的低11位用於存放負載的小數部分,高21位用於存放整數部分。當進程所耗的 CPU時間片數超過CPU在5秒內能夠提供的時間片數時,內核計算上述的三個負載,負載初始化為0。
假設最近1、5、15分鐘內的平均負載分別為 load1、load5和load15,那麼下一個計算時刻到來時,內核通過下面的算式計算負載:
load1 -= load1 - exp(-5 / 60) -+ n (1 - exp(-5 / 60 ))
load5 -= load5 - exp(-5 / 300) + n (1 - exp(-5 / 300))
load15 = load15 exp(-5 / 900) + n (1 - exp(-5 / 900))
其中,exp(x)為e的x次冪,n為當前運行隊列的長度。
如何找出系統中load高時處於運行隊列的進程
通過前面的講解,我們已經明白有可能系統有很高的負載但是CPU使用率卻很低,或者負載很低而CPU利用率很高,這兩者沒有直接關係,如何用腳本統計出來處於運行隊列的進程呢?
每隔1s統計一次:
從統計出來的結果可以看到:
在load比較高的時候,有大量的nginx處於R或者D狀態,他們才是造成load上升的元兇,和我們底層的負載確實是沒有關係的。
最後也給大家share一下查CPU使用率比較高的線程小腳本:
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
推薦閱讀:
※nginx提示錯誤 Access denied.?
※利用nginx fastcgi_cache及golang-lru解決介面瓶頸
※我會這樣設計WAF系統
※nginx 基本入門
※為什麼考慮到溢出用減法來比較更好?