做者:夏明(涯海)
創做日期:2019-08-14
專欄地址: 【穩定大於一切】
CPU(Central Processing Unit)是計算機系統的運算和控制核心,是信息處理、程序運行的最終執行單元,至關於系統的「大腦」。當 CPU 過於繁忙,就像「人腦」併發處理過多的事情,會下降作事的效率,嚴重時甚至會致使崩潰「宕機」。所以,理解 CPU 的工做原理,合理控制負載,是保障系統穩定持續運行的重要手段。html
一臺機器可能包含多塊 CPU 芯片,多個 CPU 之間經過系統總線通訊。linux
一塊 CPU 芯片可能包含多個物理核,每一個物理核都是一個實打實的運算核心(包括運算器、存儲器等)。ios
超線程(Hyper-Threading)技術可讓一個物理核在單位時間內同時處理兩個線程,變成兩個邏輯核。但它不會擁有傳統單核 2 倍的處理能力,也不可能提供完整的並行處理能力。git
舉個例子,假設一個 CPU 芯片就是一個班級;它有 2 個物理核,也就是 2 個同窗,老師讓他們分別擔任班長和體育委員;過了一段時間,校長要求每一個班級還要有學習委員和生活委員,理論上還須要 2 位同窗,可是這個班級只有 2 我的,最後老師只能讓班長和體育委員兼任。github
這樣一來,對於不瞭解的人來講,這個班級有班長、體育委員、學習委員和生活委員 4 個職位,應該有 4 我的,每一個職位就是一個邏輯核;可是,實際上這個班級只有 2 位同窗,也就是隻有 2 個物理核,雖然他們能夠作 4 份工做,可是不能把他們當作 4 我的。數據庫
在 Linux 系統下,能夠從 /proc/cpuinfo
文件中讀取 CPU 信息,以下圖所示:性能優化
cat /proc/cpuinfo | grep 'physical id' | sort | uniq | wc -l
cat /proc/cpuinfo | grep 'cpu cores' | sort | uniq
cat /proc/cpuinfo | grep 'siblings' | sort | uniq
CPU 使用率就是 CPU 非空閒態運行的時間佔比,它反映了 CPU 的繁忙程度。好比,單核 CPU 1s 內非空閒態運行時間爲 0.8s,那麼它的 CPU 使用率就是 80%;雙核 CPU 1s 內非空閒態運行時間分別爲 0.4s 和 0.6s,那麼,整體 CPU 使用率就是 (0.4s + 0.6s) / (1s * 2) = 50%
,其中 2 表示 CPU 核數,多核 CPU 同理。服務器
在 Linux 系統下,使用 top 命令查看 CPU 使用狀況,能夠獲得以下信息:網絡
Cpu(s): 0.2%us, 0.1%sy, 0.0%ni, 77.5%id, 2.1%wa, 0.0%hi, 0.0%si, 20.0%st
us(user)
:表示 CPU 在用戶態運行的時間百分比,一般用戶態 CPU 高表示有應用程序比較繁忙。典型的用戶態程序包括:數據庫、Web 服務器等。sy(sys)
:表示 CPU 在內核態運行的時間百分比(不包括中斷),一般內核態 CPU 越低越好,不然表示系統存在某些瓶頸。ni(nice)
:表示用 nice 修正進程優先級的用戶態進程執行的 CPU 時間。nice 是一個進程優先級的修正值,若是進程經過它修改了優先級,則會單獨統計 CPU 開銷。id(idle)
:表示 CPU 處於空閒態的時間佔比,此時,CPU 會執行一個特定的虛擬進程,名爲 System Idle Process。wa(iowait)
:表示 CPU 在等待 I/O 操做完成所花費的時間,一般該指標越低越好,不然表示 I/O 存在瓶頸,能夠用 iostat 等命令作進一步分析。hi(hardirq)
:表示 CPU 處理硬中斷所花費的時間。硬中斷是由外設硬件(如鍵盤控制器、硬件傳感器等)發出的,須要有中斷控制器參與,特色是快速執行。si(softirq)
:表示 CPU 處理軟中斷所花費的時間。軟中斷是由軟件程序(如網絡收發、定時調度等)發出的中斷信號,特色是延遲執行。st(steal)
:表示 CPU 被其餘虛擬機佔用的時間,僅出如今多虛擬機場景。若是該指標太高,能夠檢查下宿主機或其餘虛擬機是否異常。因爲 CPU 有多種非空閒態,所以,CPU 使用率計算公式能夠總結爲:CPU 使用率 = (1 - 空閒態運行時間/總運行時間) * 100%
。併發
根據經驗法則, 建議生產系統的 CPU 總使用率不要超過 70%。
平均負載(Load Average)是指單位時間內,系統處於 可運行狀態(Running / Runnable) 和 不可中斷態 的平均進程數,也就是 平均活躍進程數。
可運行態進程包括正在使用 CPU 或者等待 CPU 的進程;不可中斷態進程是指處於內核態關鍵流程中的進程,而且該流程不可被打斷。好比當進程向磁盤寫數據時,若是被打斷,就可能出現磁盤數據與進程數據不一致。 不可中斷態,本質上是系統對進程和硬件設備的一種保護機制。
在 Linux 系統下,使用 top 命令查看平均負載,能夠獲得以下信息:
load average: 1.09, 1.12, 1.52
這 3 個數字分別表示 1分鐘、5分鐘、15分鐘內系統的平均負載。該值越小,表示系統工做量越少,負荷越低;反之負荷越高。
理想狀況下,每一個 CPU 應該滿負荷工做,而且沒有等待進程,此時,平均負載 = CPU 邏輯核數。
可是,在實際生產系統中,不建議系統滿負荷運行。通用的經驗法則是:平均負載 = 0.7 * CPU 邏輯核數
。
除了關注平均負載值自己,咱們也應關注平均負載的變化趨勢,這包含兩層含義。一是 load一、load五、load15 之間的變化趨勢;二是歷史的變化趨勢。
0.7 * CPU 邏輯核數
時,應調查緣由,下降系統負載。CPU 使用率是單位時間內 CPU 繁忙程度的統計。而平均負載不只包括正在使用 CPU 的進程,還包括等待 CPU 或 I/O 的進程。所以,二者不能等同,有兩種常見的場景以下所述:
爲了更深刻的理解 CPU 使用率與平均負載的關係,咱們舉一個例子:假設如今有一個電話亭,有 4 我的在等待打電話,電話亭同一時刻只能容納 1 我的打電話,只有拿起電話筒纔算是真正使用。
那麼 CPU 使用率就是拿起電話筒的時間佔比,它只取決於在電話亭裏的人的行爲,與平均負載沒有很是直接的關係。而平均負載是指在電話亭裏的人加上排隊的總人數,以下圖所示:
不管是 CPU 使用率,仍是平均負載,都只是反映系統健康狀態的度量指標,而不是問題的根因。所以,它們的價值主要體如今兩個方面: 一是綜合反映當前系統的健康程度,結合監控告警產品,實現快速響應;二是初步定位問題方向,縮小排查範圍,下降故障恢復時間。 好比當 CPU iowait 高時,應優先排查磁盤 I/O;當 CPU steal 高時,就優先排查宿主機狀態。
CPU 涵蓋的問題場景有不少,限於篇幅限制,下面以最多見的用戶態 CPU 使用率高爲例,介紹下 Java 應用的排查思路,其餘場景留待後續分享,推薦閱讀 《如何迅速分析出系統CPU的瓶頸在哪裏?》。
用戶態 CPU 使用率反映了應用程序的繁忙程度,一般與咱們本身寫的代碼息息相關。所以,當你在作應用發佈、配置變動或性能優化時,若是想定位消耗 CPU 最多的 Java 代碼,能夠遵循以下思路:
top
命令找到 CPU 消耗最多的進程號;top -Hp 進程號
命令找到 CPU 消耗最多的線程號(列名仍然爲 PID);printf "%x\n" 線程號
命令輸出該線程號對應的 16 進制數字;jstack 進程號 | grep 16進制線程號 -A 10
命令找到 CPU 消耗最多的線程方法堆棧。上述方法是目前業界最經常使用的診斷流程,若是是非 Java 應用,能夠將 jstack 替換爲 perf,推薦閱讀 《Perf -- Linux下的系統性能調優工具》。
然而,上述方法有兩個顯著缺陷,一是操做流程複雜,並且每每一次 jstack 還不足以定位根因,須要執行屢次;二是隻能用於診斷在線問題,若是問題已經發生,沒法復現的話,每每只能不了了之。
所以,生產系統推薦使用 APM 產品,好比阿里雲的 ARMS,能夠自動記錄每類線程的 CPU 耗時和方法棧,開箱即用,自動保留問題現場,以下圖所示:
【穩定大於一切】打造國內穩定性領域知識庫,讓沒法解決的問題少一點點,讓世界的肯定性多一點點。