作者:任坤
現居珠海,先後擔任專職 Oracle 和 MySQL DBA,現在主要負責 MySQL、mongoDB 和 Redis 維護工作。
本文來源:原創投稿
*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。
1、背景
某專案的開發環境,單臺虛擬機器裝了1套mongo叢集用於測試,1個mongos + 3節點config + 1shard * 3副本,總計7個mongo例項。 mongo版本4.2.19,OS為centos 7.9。
測試結束後cpu負載一直維持在50%左右,而此時mongo的qps已經下降為0。
這臺機器上只安裝了mongo,將所有mongo例項關閉,cpu負載立即恢復正常,再將mongo例項開啟,過了一會cpu負載又開始飆升。場景能復現,且確認是跟mongo例項有關係。
2、診斷
執行top命令,cpu的usr已經達到了40%,但是前幾個程式的%cpu加起來遠遠湊不夠數。
檢視mongos的qps,確實沒有執行使用者命令了。
dstat檢視整體負載(vmstat格式化做的不好,最後幾列總是對不齊整)。
除了cpu負載不正常,其餘指標均正常,中斷和上下文切換也不算高,不太可能是這兩個引發的。
perf record -ag -- sleep 10 && perf report 檢視cpu執行情況。
確實有大量mongo呼叫,但是API命名不直觀,無法猜測對應的執行邏輯。
至此,確認是mongo例項引發的問題,但是mongo的應用連線為0,看呼叫API棧也找不到有用資訊。
回到本文開頭,top程式的cpu利用率加起來遠遠小於cpu總體負載,大概率是有頻繁短時程式偷走了這部分CPU資源,導致top命令來不及捕獲統計。
sar -w 1 檢視每秒生成的程式數,平均每秒新建80多個程式,應該就是它了。
要抓出頻繁建立短時程式的應用,可以採用execsnoop,該工具通過 ftrace 實時監控程式的 exec() 行為,並輸出短時程式的基本資訊, 包括程式 PID/PPID、命令列引數。
#下載execsnoop#
cd /usr/bin
wget https://raw.githubusercontent.com/brendangregg/perf‐tools/master/execsnoop
chmod 755 execsnoop
以下是輸出內容,全是監控系統在執行,不停的連線mongo並對輸出結果執行grep過濾,每個操作都會衍生一個新執行緒/程式,10s捕獲 了400多條記錄。
將zabixx程式關閉,cpu馬上恢復正常,找到了元凶。
我們其他環境也採用了zabbix監控,但是都沒有遇到類似問題。
該節點部署了7個mongo例項,zabbix預設對每個mongo例項都進行監控,相當於執行損耗放大了7倍,而該機器是一臺只有4核CPU的虛擬機器。
這些因素湊齊了就會爆發問題。 這是個開發環境,暫時關閉了zabbix監控,後續要對監控邏輯進行優化,儘量減少連線db的次數以及grep呼叫鏈的長度。
3、小結
當機器cpu負載持續高漲卻抓取不到top程式時,可以採用execsnoop抓取短時程式,類似工具還有iosnoop、opensnoop。