K8S下應用異常卡頓問題的分析與學習

济南小老虎發表於2024-05-18

K8S下應用異常卡頓問題的分析與學習


背景

週二自己在處理申威伺服器的問題時, 被同事拉進一個群聊.
告知客戶現場有一個特殊情況: 
服務晚上重啟,  上午速度還可以, 但是到了下午就開始變的非常卡頓.

因為當時正在車上也看不到具體資訊. 
晚上九點上會進行了一次簡單檢視.

發現GC非常平穩, 容器內的CPU和記憶體都和很正常
部署模式是 華為鯤鵬伺服器上面的 華為雲 K8S叢集
容器部署.

第一次問題分析

第一天沒有上手操作(這是一個敗筆)
根據現場同事的說明進行了簡單的判斷. 

啟動引數問題不大, 資源沒問題 , GC沒問題
同事一開始懷疑是 虛擬化擠壓導致的效能下降
我透過gclog發現GC時間變化不大, 排除了這一個可能. 

但是懷疑自己分析錯了 top -Hp的檔案,導致出現誤判
懷疑的方向到了 東方通中介軟體. 以為是中介軟體的問題. 

第二次問題分析

週三下午問題依舊. 
不過也排除了東方通的問題, 不算是沒收穫.
沒辦法緊急聯絡了華為雲的運維人員
進行了一些簡單的溝通
發現大家都一樣, 認為自己沒問題. 
都是別人的問題. 
雲平臺說別人沒問題, 就你們有問題
我們說大專案都沒問題,就這個專案有問題.
沒辦法繼續折騰 

週三其實沒有特別大的發現, 想著繼續看看

第三次問題分析

週四下午問題繼續 !-_-!
正好下午有時間可以遠端, 趁著六點客戶使用低谷期進行了驗證
週三其實還是有一個收穫的, 看到華為雲有一個jvm的監控
週四自己能操作, 多看了會兒, 發現 codecache 是一個深坑, 只有 48MB
然後繼續上手操作: 
其實方法還是一樣的. 
第一步 docker exec -it $containerid bash 進入容器
第二步 top -Hp 16 然後輸入大寫的 T  檢視 現成CPU使用時間
這裡存在一個坑爹的問題, 容器內不顯示具體執行緒資訊, 只顯示java
第三步 jstack -l 16 > 1.txt 然後 cat 1.txt |grep C2 
檢視C2 編譯程序的 程序號 發現是 nid=0x32 和 nid=0x33
檢視第一步裡面的 50號和51號執行緒, 發下CPU使用率已經超過了80分鐘. 
注意這裡需要進行 16進位制和10進位制的轉換. 

基本確認 產品應該是 codecache 太小導致的問題. 

問題解決

增加啟動指令碼: 
-XX:InitialCodeCacheSize=1G  -XX:ReservedCodeCacheSize=1G  

第二天進行檢視. 
發現 時間基本可控了. 

問題原因確定

拿現場的JDK 到公司內部進行驗證
替換自己的aarch64的 jdk 進行處理
檔名為:
jdk-8u221-linux-arm64-vfp-hflt.tar.gz
替換之後進行啟動. 發現
 cat jdk1.8.221.txt |grep C2
"C2 CompilerThread1" #6 daemon prio=9 
"C2 CompilerThread0" #5 daemon prio=9 
只有C2沒有C1
[root@NFSV3 ~]# cat jdk1.8.221.txt |grep C1

之前的jdk的情況是: 
[root@NFSV3 ~]# cat jdk18222.txt |grep C1
"C1 CompilerThread20" #25 daemon prio=9 
"C1 CompilerThread19" #24 daemon prio=9 
"C1 CompilerThread18" #23 daemon prio=9 
"C1 CompilerThread17" #22 daemon prio=9 
"C1 CompilerThread16" #21 daemon prio=9 
"C1 CompilerThread15" #20 daemon prio=9 
"C1 CompilerThread14" #19 daemon prio=9 

現場的JDK版本存在問題.  一方面太久, 並且是一個prerelease的.

問題進一步的思考

這個簡單的問題浪費了兩天的時間
(主要是有其他事情在, 自己沒直接上手.)

但是不想浪費時間就這麼白白浪費了
趁著幫人解決問題, 想多進行一下思考和資料獲取

第一個: 為什麼我這邊正常情況下 伺服器返回而也有 300ms.
不應該這麼多的, 公司內x86的機器才  20ms左右
自己想到了網路延遲, 然後ping了下,發現延遲在 40ms. 
自己與專案所在地的距離應該是
好幾千公里.  所以理論上在區域網應該會少40ms
然後讓交付進行了驗證, 的確現場大概是 250ms 左右

第二個: 想到了是容器化部署的情況
我讓交付同事直接使用node:port的方式進行檢視時延的情況
發現延遲也差不多 250ms
所以懷疑 K8S的出口有一個較大行的網路裝置影響了網路延遲. 
公司內最快15ms.明顯網路裝置產生了 240ms的延遲. 

問題進一步思考之二

為啥方法區預設是48MB
現場同事很細心, 立馬發現 分層編譯時預設值是 240MB
不啟用分層編譯是  48MB
但是我們沒有明確在指定不使用分層編譯
所以這是一個什麼鬼? 

又花費了了一段時間進行排查, 暫未發現
感覺可以問問呢 華為雲或者是 jdk的版本? 

問題的進一步思考之三

其實如果有perf 或者是 epbf 
或者是使用arthas 或者是 async profiler
可以透過檢視火焰圖裡面大的平臺
如果升級jdk 可以使用jfr 然後同構jmc進行分析

估計也可以看到是 complie 相關
也可以確定這個問題原因
但是現場沒有部署這一些工具, 部署工具有擔心影響效能. 

所以很多問題是需要循序漸進的. 
提高自己的武器庫才重要
不能盲猜不能盲信. 

問題的進一步思考之四

需要統一交付物
這幾天幫助同事進行處理. 
他找了一圈都沒找到openjdk的下載點
自己下載的這個jdk有bug 
也不能怪這位同事.

還是需要有一個統一的知識庫和可以獲取下載的點的. 

相關文章