記一次tomcat進(jìn)程cpu占用過高的問題排查記錄
本文主要記錄一次tomcat進(jìn)程,因TCP連接過多導(dǎo)致CPU占用過高的問題排查記錄。
問題描述
linux系統(tǒng)下,一個tomcat web服務(wù)的cpu占用率非常高,top顯示結(jié)果超過200%。請求無法響應(yīng)。反復(fù)重啟依然同一個現(xiàn)象。
問題排查
1、獲取進(jìn)程信息
通過jdk提供的jps命令可以快速查出jvm進(jìn)程,
jps pid
2、查看jstack信息
jstack pid
發(fā)現(xiàn)存在大量log4j線程block,處于waiting lock狀態(tài)
org.apache.log4j.Category.callAppenders(org.apache.log4j.spi.LoggingEvent) @bci=12, line=201 (Compiled frame)
搜索相關(guān)信息,發(fā)現(xiàn)log4j 1.x版本存在死鎖問題。
發(fā)現(xiàn)問題,于是調(diào)整log4j配置,僅打開error級別日志,重啟tomcat。此時stack中block線程消失,但進(jìn)程cpu占用率依然高漲。
3、進(jìn)一步排查
分析每個線程的cpu占用量,此處需要引入一個大神貢獻(xiàn)的腳本,計算java進(jìn)程中,每個線程的cpu使用量。
#!/bin/bash typeset top=${1:-10} typeset pid=${2:-$(pgrep -u $USER java)} typeset tmp_file=/tmp/java_${pid}_$$.trace $JAVA_HOME/bin/jstack $pid > $tmp_file ps H -eo user,pid,ppid,tid,time,%cpu --sort=%cpu --no-headers\ | tail -$top\ | awk -v "pid=$pid" '$2==pid{print $4"\t"$6}'\ | while read line; do typeset nid=$(echo "$line"|awk '{printf("0x%x",$1)}') typeset cpu=$(echo "$line"|awk '{print $2}') awk -v "cpu=$cpu" '/nid='"$nid"'/,/^$/{print $0"\t"(isF++?"":"cpu="cpu"%");}' $tmp_file done rm -f $tmp_file
腳本適用范圍
因?yàn)閜s中的%CPU數(shù)據(jù)統(tǒng)計來自于/proc/stat,這個份數(shù)據(jù)并非實(shí)時的,而是取決于OS對其更新的頻率,一般為1S。所以你看到的數(shù)據(jù)統(tǒng)計會和jstack出來的信息不一致也就是這個原因~但這份信息對持續(xù)LOAD由少數(shù)幾個線程導(dǎo)致的問題排查還是非常給力的,因?yàn)檫@些固定少數(shù)幾個線程會持續(xù)消耗CPU的資源,即使存在時間差,反正也都是這幾個線程所導(dǎo)致。
除了這個腳本,簡單點(diǎn)兒的方法則是,查出進(jìn)程id后,通過如下命令查看該進(jìn)程中每個線程的資源使用情況
top -H -p pid
從這里獲取pid(線程id),轉(zhuǎn)換為16進(jìn)制,然后去stack信息中查找對象的線程信息。
通過上述方法,查出tomcat進(jìn)程對應(yīng)的線程cpu占用率累積之和約80%,遠(yuǎn)小于top給出的200%+
說明并不存在長期占用cpu的線程,應(yīng)該是屬于有許多短暫性的cpu密集計算。進(jìn)而懷疑是不是jvm內(nèi)存不足,頻繁gc導(dǎo)致。
jstat -gc pid
發(fā)現(xiàn)jvm內(nèi)存使用并未出現(xiàn)異常,gc次數(shù)明顯暴漲
查完內(nèi)存,由于本身是一個網(wǎng)絡(luò)程序,進(jìn)一步排查網(wǎng)絡(luò)連接。
4、問題定位
查詢tomcat對應(yīng)端口的tcp鏈接,發(fā)現(xiàn)存在大量EASTABLISH的鏈接,還有部分其它狀態(tài)的連接,總計400+。
netstat -anp | grep port
進(jìn)一步查看這些連接的來源,發(fā)現(xiàn)是該tomcat服務(wù)的應(yīng)用端,存在大量后臺線程,在頻繁輪詢該服務(wù),導(dǎo)致該服務(wù)tomcat 連接數(shù)被打滿,無法繼續(xù)接收請求。
netstat狀態(tài)說明:
- LISTEN:偵聽來自遠(yuǎn)方的TCP端口的連接請求
- SYN-SENT:再發(fā)送連接請求后等待匹配的連接請求(如果有大量這樣的狀態(tài)包,檢查是否中招了)
- SYN-RECEIVED:再收到和發(fā)送一個連接請求后等待對方對連接請求的確認(rèn)(如有大量此狀態(tài),估計被flood***了)
- ESTABLISHED:代表一個打開的連接
- FIN-WAIT-1:等待遠(yuǎn)程TCP連接中斷請求,或先前的連接中斷請求的確認(rèn)
- FIN-WAIT-2:從遠(yuǎn)程TCP等待連接中斷請求
- CLOSE-WAIT:等待從本地用戶發(fā)來的連接中斷請求
- CLOSING:等待遠(yuǎn)程TCP對連接中斷的確認(rèn)
- LAST-ACK:等待原來的發(fā)向遠(yuǎn)程TCP的連接中斷請求的確認(rèn)(不是什么好東西,此項(xiàng)出現(xiàn),檢查是否被***)
- TIME-WAIT:等待足夠的時間以確保遠(yuǎn)程TCP接收到連接中斷請求的確認(rèn)
- CLOSED:沒有任何連接狀態(tài)
5、根源分析
直接觸發(fā)原因是客戶端輪詢,請求異常,繼續(xù)輪序;客戶端不斷有新的后臺線程加入輪詢隊伍,最終導(dǎo)致服務(wù)端tomcat連接被打滿。
到此這篇關(guān)于記一次tomcat進(jìn)程cpu占用過高的問題排查記錄的文章就介紹到這了,更多相關(guān)tomcat進(jìn)程cpu占用過高內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
tomcat9 下載安裝和配置+整合到eclipse的教程詳解
這篇文章主要介紹了tomcat9 下載安裝和配置+整合到eclipse,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07詳解從源碼分析tomcat如何調(diào)用Servlet的初始化
這篇文章主要介紹了詳解從源碼分析tomcat如何調(diào)用Servlet的初始化,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04詳解用Tomcat服務(wù)器配置https雙向認(rèn)證過程實(shí)戰(zhàn)
本篇文章主要介紹了詳解用Tomcat服務(wù)器配置https雙向認(rèn)證過程實(shí)戰(zhàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05tomcat報錯:地址localhost:8080已在使用中的解決方法
今天使用tomcat發(fā)現(xiàn)一個問題,本文就介紹一下報錯地址localhost:8080已在使用中的解決方法,具有一定的參考價值,感興趣的可以了解一下2023-05-05tomcat之目錄映射_動力節(jié)點(diǎn)Java學(xué)院整理
一個web應(yīng)用包含了許多我們做好的web資源,里面或許包括了多個靜態(tài)web資源和動態(tài)web資源,而我們都知道服務(wù)器的虛擬目錄映射有三種方式,具體哪三種方式,感興趣的朋友可以通過本文學(xué)習(xí)2017-07-07Tomcat9安裝windows服務(wù)的詳細(xì)教程
這篇文章主要介紹了Tomcat9安裝windows服務(wù)的教程,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11關(guān)于Tomcat?結(jié)合Atomikos?實(shí)現(xiàn)JTA的方法
Tomcat作為一款經(jīng)典的Web服務(wù)器,在開發(fā)、測試和生產(chǎn)環(huán)境中得到了廣泛的使用。但Tomcat畢竟不是Java EE服務(wù)器,因此在EJB,JTA方面并沒有提供支持。本文講述了Tomcat使用Atomikos實(shí)現(xiàn)JTA的一種方法,需要的朋友可以參考下2021-11-11