告警
正在開會陌凳,突然釘釘告警聲響個不停,同時市場人員反饋客戶在投訴系統(tǒng)登不進了,報504錯誤匿乃。查看釘釘上的告警信息桩皿,幾臺業(yè)務服務器節(jié)點全部報CPU超過告警閾值,達100%幢炸。
趕緊從會上下來泄隔,SSH登陸服務器,使用 top 命令查看宛徊,幾個Java進程CPU占用達到180%佛嬉,190%,這幾個Java進程對應同一個業(yè)務服務的幾個Pod(或容器)闸天。
定位
1. 使用 docker stats 命令查看本節(jié)點容器資源使用情況暖呕,對占用CPU很高的容器使用
?docker exec -it <容器ID> bash 進入。
2.?在容器內(nèi)部執(zhí)行 top 命令查看苞氮,定位到占用CPU高的進程ID湾揽,使用 top -Hp <進程ID> 定位到占用CPU高的線程ID。
3.?使用 jstack <進程ID> > jstack.txt 將進程的線程棧打印輸出
4.?退出容器笼吟, 使用 docker cp <容器ID>:/usr/local/tomcat/jstack.txt ./ 命令將jstack文件復制到宿主機库物,便于查看。獲取到jstack信息后贷帮,趕緊重啟服務讓服務恢復可用戚揭。
5.?將2中占用CPU高的線程ID使用 pringf '%x\n' <線程ID> 命令將線程ID轉(zhuǎn)換為十六進制形式。假設線程ID為133撵枢,則得到十六進制85毫目。在jstack.txt文件中定位到 nid=0x85的位置,該位置即為占用CPU高線程的執(zhí)行棧信息诲侮。如下圖所示
6.??與同事確認镀虐,該處為使用一個框架的excel導出功能,并且沟绪,導出excel時沒有分頁刮便,沒有限制!!!查看SQL查詢記錄,該導出功能一次導出50w條數(shù)據(jù)绽慈,并且每條數(shù)據(jù)都需要做轉(zhuǎn)換計算恨旱,更為糟糕的是,操作者因為導出時久久沒有響應坝疼,于是連續(xù)點擊搜贤,幾分鐘內(nèi)發(fā)起了10多次的導出請求……于是,CPU被打滿钝凶,服務崩潰了仪芒,我也崩潰了。
解決
對于此類耗資源的操作,一定要做好相應的限制掂名。比如可以限制請求量据沈,控制最大分頁大小,同時可以限制訪問頻率饺蔑,比如同一用戶一分鐘內(nèi)最多請求多少次锌介。
再發(fā)
服務重啟后恢復。到了下午猾警,又一臺服務器節(jié)點CPU告警孔祸,依前面步驟定位到占用CPU高的線程,如下
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fa114020800 nid=0x10 runnable?"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fa114022000 nid=0x11 runnable
使用命令 jstat -gcutil <進程ID> 2000 10 查看GC情況发皿,如圖
發(fā)現(xiàn)Full GC次數(shù)達到1000多次融击,且還在不斷增長,同時Eden區(qū)雳窟,Old區(qū)已經(jīng)被占滿(也可使用jmap -heap <進程ID>查看堆內(nèi)存各區(qū)的占用情況)尊浪,使用jmap將內(nèi)存使用情況dump出來,
jmap -dump:format=b,file=./jmap.dump 13
退出容器封救,使用 docker cp <容器ID>:/usr/local/tomcat/jmap.dump ./ 將dump文件復制到宿主機目錄拇涤,下載到本地,使用 MemoryAnalyzer誉结,如圖
如果dump文件比較大鹅士,需要增大MemoryAnalyzer.ini配置文件中的-Xmx值
發(fā)現(xiàn)占用內(nèi)存最多的是char[], String對象,通過右鍵可以查看引用對象惩坑,但點開貌似也看不出所以然來掉盅,進入內(nèi)存泄露報告頁面,如圖
該頁面統(tǒng)計了堆內(nèi)存的占用情況以舒,并且給出疑似泄露點趾痘,在上圖中點開“see stacktrace”鏈接,進入線程棧頁面蔓钟,
似曾熟悉的畫面永票,還是跟excel導出有關,數(shù)據(jù)太多滥沫,導致內(nèi)存溢出……于是GC頻繁侣集,于是CPU爆了。根源還是同一個兰绣。
總結(jié)
本文以處理一次線上服務CPU 100%的實戰(zhàn)過程示例了在遇到Java服務造成服務器CPU消耗過高或內(nèi)存溢出的一般處理方法世分,希望對大家定位線上類似問題提供參考。同時缀辩,開發(fā)實現(xiàn)功能時需要考慮的更深遠一些臭埋,不能停留在解決當前的場景踪央,需要考慮數(shù)據(jù)量不斷增大時,你的實現(xiàn)是否還能適用斋泄。俗話說杯瞻,初級程序員解決當前問題镐牺,中級程序員解決兩年后的問題炫掐,高級程序員解決五年后的問題。