使用tomcat java進程佔用cpu偏高的原因

使用tomcat做爲java容器,cpu佔用偏高的原因,目前公司服務器上面跑的ubuntu環境nginx+tomcat+mysql運行一段時間之後java進程cpu偏高,會出現網站打不開的情況。所以進行了如下分析。


一,首先查看tomcat日誌,如果有出現OOM錯誤(內存溢出)可以對應的加大jvm的內存大小。

1,修改tomcat目錄下bin目錄下的catalina.sh文件,在

#JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`"

這行下面添加如下內容


JAVA_OPTS="-server -Xms2048m -Xmx2048m -Xmn512m -XX:PermSize=256M -XX:MaxPermSize=256m -Xss256k -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=20 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=73 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=2 -Djava.awt.headless=true"


上面的配置是基於4G內存設置的,具體修改看自己手上服務器的配置。

參數的含義:

-server 告訴tomcat使用server模式 能獲得更大併發數和性能

-Xms2048m -Xmx2048m JVM內存的總數

-Xmn512m 年輕代內存大小

-XX:PermSize=256M -XX:MaxPermSize=256m 永久帶內存大小

Xss256k 線程大小

-XX:SurvivorRatio=4 設置年輕代中Eden區與Survivor區的大小比值。設置爲4,則兩個Survivor區與一個Eden區的比值爲2:4,一個Survivor區佔整個年輕代的1/6

-XX:MaxTenuringThreshold=20 設置垃圾最大年齡。如果設置爲0的話,則年輕代對象不經過Survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設置爲一個較大值,則年輕代對象會在Survivor區進行多次複製,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概率

-XX:+UseParNewGC 對年輕代採用多線程並行回收,這樣收得快

XX:+UseConcMarkSweepGC

CMS gc,這一特性只有jdk1.5即後續版本才具有的功能,它使用的是gc估算觸發和heap佔用觸發。

我們知道頻頻繁的GC會造面JVM的大起大落從而影響到系統的效率,因此使用了CMS GC後可以在GC次數增多的情況下,每次GC的響應時間卻很短,比如說使用了CMS GC後經過jprofiler的觀察,GC被觸發次數非常多,而每次GC耗時僅爲幾毫秒

-XX:CMSInitiatingOccupancyFraction=73 說明年老代到73%滿的時候開始執行對年老代的併發垃圾回收(CMS)。

-XX:+UseCMSCompactAtFullCollection 打開對年老代的壓縮。可能會影響性能,但是可以消除碎片

-XX:+CMSParallelRemarkEnabled 降低標記停頓

-XX:CMSFullGCsBeforeCompaction 由於併發收集器不對內存空間進行壓縮、整理,所以運行一段時間以後會產生“碎片”,使得運行效率降低。此值設置運行多少次GC以後對內存空間進行壓縮、整理。


參考網站:http://blog.csdn.net/lifetragedy/article/details/7708724


2,修改參數之後重啓tomcat,查看參數是否生效

jmap -heap javaPID 查看JVM內存分配情況

jstat -gcutil javaPID 1000 30 查看JVM內存回收情況


經過上面的修改應該就可以完成對tomcat進程飆高的情況了。如果運行一段時間之後通過jstat查看各個內存代的使用情況,發現老年代100% 一直在觸發FULL GC 那就是內存大小的原因了。有條件的可以添加內存,沒條件的可以設置 每天重啓一次tomcat或者一個星期重啓一次來釋放jvm內存。問題解決。


二,如果想查看是否是代碼層的原因,就需要另外的辦法

1,使用命令jstack命令查看佔用CPU最高的線程。

PID=`ps aux | grep java | head -1 | awk '{print $2}'`

ps -mp $PID -o THREAD,tid,time | sort -k 2 -r | head -20


echo -n -e " shur ru:"

read f


if [ -z $f ]

then

echo "no"

else

jstack "$PID" | grep `printf "%x\n" $f` -A 30

fi

一個簡單的監控腳本,查看JAVA進程佔用CPU最高的線程在做什麼以此來分析是否是代碼層的問題。

參考網站:http://blog.csdn.net/blade2001/article/details/9065985


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