標籤:

找到Linux虛機Load高的"元兇"

摘要: 本篇文章從linux load原理角度出發,通過簡單的Linux ps命令編寫腳本,找到虛機內部導致load高的進程。

原文:click.aliyun.com/m/4244

問題描述

有客戶反饋他們的一台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 基本入門
為什麼考慮到溢出用減法來比較更好?

TAG:Nginx | Linux | 線程 |