load高但是cpu佔用率低的排查

CPU不高的情況,一遍cpu的wait或idle都有較大的值,表明CPU利用率不高

1. 一種情況是磁盤IO過高,導致線程等待

使用vmstat 命令,查看io的情況。
vmstat 2 5

或使用iotop工具,默認顯示對IO高低進行倒序實時顯示,其中tid即是pid

Ubuntu:apt-get install iotop -y

2. 另一種情況,比較複雜,可能是運行的應用線程頻繁切換導致

load 呈現的是CPU等待處理的請求隊列的壓力,load太高表明有太多請求等待處理

參考 https://www.isolves.com/it/wl/js/2020-06-01/19173.html,下面摘錄部分,更多見原文

排查導致load高的原因
tips:系統load高,不代表cpu資源不足。Load高只是代表需要運行的隊列累計過多。但隊列中的任務實際可能是耗cpu的,也可能是耗i/0及其他因素的

vmstat 2 5
查看系統整體運行狀態
io的bi(block in)--bo(block out)列,表示I/O狀態。
system的中斷數(in)、上下文切換(cs)特別頻繁,進程上下文切換次數較多的情況下,很容易導致CPU將大量的時間耗費在寄存器、內核棧、以及虛擬內存等資源的保存和恢復上,進而縮短了真正運行進程的時間造成load高。

CPU寄存器,是CPU內置的容量小、但速度極快的內存。程序計數器,則是用來存儲CPU正在執行的指令的位置,或者即將執行的下一條指令的位置。
他們都是CPU在運行任何任務前,必須依賴的環境,因此也被叫做CPU上下文。

CPU上下文切換,就是先把前一個任務的CPU上下文(也就是CPU寄存器和程序計數器)保存起來,然後加載新任務的上下文,到這些寄存器和程序計數器,最後再跳轉到程序計數器所指的新位置,運行新任務。

排查大方向:頻繁的中斷以及線程切換(由於該臺ecs上只存在一個JAVA服務,主要排查該進程)

通過vmstate只能查看總的cpu上下文切換,可通過pidstat命令查看線程層面的上下文切換信息 pidstat -wt 1 (1表示每1秒刷新一次)

如運行Java服務:
第一個是java線程特別多
第二個是很有規律的出現每秒上下文切換100+次的線程。
確認一下這些java線程的來源,查看該應用進程下的線程數
cat /proc/17207/status
線程數9749(非高峯)

排查方向:
線程數過多
部分線程每秒上下文切換次數過高
先排查主要原因,即部分線程上下文切換次數過高 拉一下線上該進程的堆棧信息,然後找到切換次數達到100+/每秒的線程id,把線程id轉成16進制後在堆棧日誌中檢索

其他參考:
https://www.cnblogs.com/lddbupt/p/5779655.html

cpu load高的排查思路
1. 首先排查哪些進程cpu佔用率高。 通過命令 ps ux
image

2. 查看對應java進程的每個線程的CPU佔用率。通過命令:ps -Lp 15047 cu
image

3. 追蹤線程內部,查看load過高原因。通過命令:jstack 15047。
或者打印線程 jstack pidof java > stack.out

查找到對應的threadid, 再反查代碼。

一般經驗
cpu load的飆升,一方面可能和full gc的次數增大有關,一方面可能和死循環有關係

數據庫系統load高的一般原因
1 業務併發調用全表掃描/帶有order by 排序的SQL語句.
2 SQL語句沒有合適索引/執行計劃出錯/update/delete where掃描全表,阻塞其他訪問相同表的sql執行.
3 存在秒殺類似的業務比如聚划算10點開團或者雙十一秒殺,瞬時海量訪問給數據庫帶來衝擊。
4 數據庫做邏輯備份(需要全表掃描)或者多實例的壓縮備份(壓縮時需要大量的cpu計算,會導致系統服務器load飆高)
5 磁盤寫入方式改變 比如有writeback 變爲 write through
RAID卡都有寫cache(Battery Backed Write Cache),寫cache對IO性能的提升非常明顯,因爲掉電會丟失數據,所以必須由電池提供支持。
電池會定期充放電,一般爲90天左右,當發現電量低於某個閥值時,會將寫cache策略從writeback置爲writethrough,相當於寫cache會失效,這時如果系統有大量的IO操作,可能會明顯感覺到IO響應速度變慢,cpu 隊列堆積系統load 飆高。

判別和處理load高問題
一般根據cpu數量去判斷,也就是Load平均要小於CPU的數量,負載的正常值在不同的系統中有着很大的差別。在單核處理器的工作站中,1或2都是可以接受的。多核處理器的服務器(比如24核)上,load 會到達20 ,甚至更高。

a) 數據庫層面
1 top -u mysql -c 檢查當前佔用cpu資源最多的進程命令。-c是爲了顯示出進程對應的執行命令語句,方便查看是什麼操作導致系統load飆高。
2 根據不同的情況獲取pid 或者MySQL的端口號
3 如果是MySQL 數據庫服務導致laod 飆高,則可以使用如下命令
show processlist;
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND <> 'sleep' AND TIME>100;

orzdba 工具檢查邏輯讀/thread active的值。用法:orzdba --help
orztop 工具檢查當前正在執行的慢sql,用法:orztop -P $port
4 獲取異常的sql之後,剩下的比較好解決了。結合第一部分中的幾條原因
a 選擇合適的索引
b 調整sql語句 比如對應order by分頁採用延遲關聯
c 業務層面增加緩存,減少對數據庫的直接訪問等
b) OS 系統層面 檢查系統IO
使用iostat -x命令查看r/s(讀請求)、w/s(寫請求)、avgrq-sz(平均請求大小)、await(IO等待)、svctm(IO響應時間)
r/s、w/s是每秒讀/寫請求的次數。

util是設備的利用率。如果它接近100%,通常說明設備能力趨於飽和(並不絕對,比如設備有寫緩存)。有時候可能會出現大於100%的情況,這多半是計算時四捨五入引起的。
svctm是平均每次請求的服務時間。這裏有一個公式:(r/s+w/s)*(svctm/1000)=util。舉例子:如果util達到100%,那麼此時svctm=1000/(r/s+w/s),假設IOPS是1000,則svctm大概在1毫秒左右,如果長時間大於這個數值,說明系統出了問題。
await是平均每次請求的等待時間。這個時間包括了隊列時間和服務時間,也就是說,一般情況下,await大於svctm,它們的差值越小,隊列時間越短,反之差值越大,隊列時間越長,說明系統出了問題。
avgqu-sz是平均請求隊列的長度。毫無疑問,隊列長度越短越好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章