【生產環境】Tomcat運行一段時間后訪問變慢分析歷程


環境運行一天或者幾天,網站訪問就很卡,手機端app訪問頁面出現白屏。Tomcat運行一段時間后訪問變慢,但是cpu,內存都正常。日志也是發現不了啥....

問題的原先分析

1.環境配置(cpu,內存,使用工具:nmon工具、visualvm工具、jprofiler工具全部用上監控中)

2.修改info日志,啟用error級別日志(待篩選排查)

3.查看數據庫配置連接池(正常)

4.代碼問題對象創建太多(待排查,web里面走攔截器待看)

5.jvm分配內存太少了(調優,生產環境重啟)

6.並發高了,網站太多人訪問(排除)

7.webapps下面的工程太多了(排除)

8.數據壓力太大數據盤大(排除)

9.物理機器問題、網絡寬度問題...

Linux環境配置信息

Tomcat啟動行參數的優化

修改前:

JAVA_OPTS="-Xmx2048m -Xms1024m -Xmn384M -XX:MaxPermSize=512m -XX:PermSize=128m"
進行重修調整,修改后:

JAVA_OPTS="-server -Xmx2048m -Xms2048m -Xmn384M -XX:PermSize=512m -XX:MaxPermSize=512m -Xss512k -XX:+AggressiveOpts -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:-UseGCOverheadLimit -XX:+HeapDumpOnOutOfMemoryError -XX:CMSInitiatingOccupancyFraction=75 -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djava.awt.headless=true "
參數解釋:

-server :

tomcat是運行在生產環境中的,這個參數必須上,因為tomcat默認是以一種叫java –client的模式來運行的,server即意味着你的tomcat是以真實的production的模式在運行的,這也就意味着tomcat以server模式運行時將擁有:更大、更高的並發處理能力,更快更強捷的JVM垃圾回收機制,可以獲得更多的負載與吞吐量更等

-Xmx2048m -Xms2048m

即JVM內存設置了,把Xms與Xmx兩個值設成一樣是最優的做法。存放 new MyClass() 的對象,是GC的主要區域,-Xms / -Xmx 分別是堆的初始容量、最大可擴展容量,建議初始值設置為最大值,以免反復擴展或縮減的開銷;

-Xmx2048m:設置JVM最大可用內存為2048M。
-Xms2048m:設置JVM促使內存為3550m。此值可以設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。

-Xmn512m

設置年輕代大小為512m。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8。

-XX:PermSize=512m -XX:MaxPermSize=512m

JVM使用-XX:PermSize設置非堆內存初始值,默認是物理內存的1/64;在數據量的很大的文件導出時,一定要把這兩個值設置上,否則會出現內存溢出的錯誤。由XX:MaxPermSize設置最大非堆內存的大小,默認是物理內存的1/4。那么,如果是物理內存4GB,那么64分之一就是64MB,這就是PermSize默認值,也就是永生代內存初始大小;四分之一是1024MB,這就是MaxPermSize默認大小。

-Xss512k

是指設定每個線程的堆棧大小。這個就要依據你的程序,看一個線程 大約需要占用多少內存,可能會有多少線程同時運行等。一般不易設置超過1M,要不然容易出現out ofmemory。

設置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。

-XX:+AggressiveOpts

作用如其名(aggressive),啟用這個參數,則每當JDK版本升級時,你的JVM都會使用最新加入的優化技術(如果有的話)

-XX:+DisableExplicitGC

在程序代碼中不允許有顯示的調用”System.gc()”。看到過有兩個極品工程中每次在DAO操作結束時手動調用System.gc()一下,覺得這樣做好像能夠解決它們的out ofmemory問題一樣,付出的代價就是系統響應時間嚴重降低,就和我在關於Xms,Xmx里的解釋的原理一樣,這樣去調用GC導致系統的JVM大起大落,

-XX:+UseBiasedLocking

啟用一個優化了的線程鎖,我們知道在我們的appserver,每個http請求就是一個線程,有的請求短有的請求長,就會有請求排隊的現象,甚至還會出現線程阻塞,這個優化了的線程鎖使得你的appserver內對線程處理自動進行最優調配。

-XX:MaxTenuringThreshold=31

設置垃圾最大年齡。如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設置為一個較大值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概率。這個值的設置是根據本地的jprofiler監控后得到的一個理想的值,不能一概而論原搬照抄。

-XX:+UseConcMarkSweepGC

即CMS gc,這一特性只有jdk1.5即后續版本才具有的功能,它使用的是gc估算觸發和heap占用觸發。我們知道頻頻繁的GC會造面JVM的大起大落從而影響到系統的效率,因此使用了CMS GC后可以在GC次數增多的情況下,每次GC的響應時間卻很短,比如說使用了CMS GC后經過jprofiler的觀察,GC被觸發次數非常多,而每次GC耗時僅為幾毫秒。

-XX:+UseParNewGC

對年輕代采用多線程並行回收,這樣收得快。

-XX:+CMSParallelRemarkEnabled

在使用UseParNewGC 的情況下, 盡量減少 mark 的時間

-XX:+UseCMSCompactAtFullCollection

在使用concurrent gc 的情況下, 防止 memoryfragmention, 對live object 進行整理, 使 memory 碎片減少。

-XX:LargePageSizeInBytes=128m

指定 Java heap的分頁頁面大小

-XX:+UseFastAccessorMethods

get,set 方法轉成本地代碼

-XX:+UseCMSInitiatingOccupancyOnly

指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 啟動收集

-XX:CMSInitiatingOccupancyFraction=70

CMSInitiatingOccupancyFraction,這個參數設置有很大技巧,基本上滿足(Xmx-Xmn)(100- CMSInitiatingOccupancyFraction)/100>=Xmn就不會出現promotion failed。在我的應用中Xmx是6000,Xmn是512,那么Xmx-Xmn是5488兆,也就是年老代有5488 兆,CMSInitiatingOccupancyFraction=90說明年老代到90%滿的時候開始執行對年老代的並發垃圾回收(CMS),這時還 剩10%的空間是548810%=548兆,所以即使Xmn(也就是年輕代共512兆)里所有對象都搬到年老代里,548兆的空間也足夠了,所以只要滿 足上面的公式,就不會出現垃圾回收時的promotion failed;

因此這個參數的設置必須與Xmn關聯在一起。

-XX:-UseGCOverheadLimit

-XX:+HeapDumpOnOutOfMemoryError

-XX:CMSInitiatingOccupancyFraction=75

-XX:CMSFullGCsBeforeCompaction=2

-XX:SoftRefLRUPolicyMSPerMB=0

-Djava.awt.headless=true

這個參數一般我們都是放在最后使用的,這全參數的作用是這樣的,有時我們會在我們的J2EE工程中使用一些圖表工具如:jfreechart,用於在web網頁輸出GIF/JPG等流,在winodws環境下,一般我們的app server在輸出圖形時不會碰到什么問題,但是在linux/unix環境下經常會碰到一個exception導致你在winodws開發環境下圖片顯示的好好可是在linux/unix下卻顯示不出來,因此加上這個參數以免避這樣的情況出現。

-XX:+UseParallelOldGC

-XX:+PrintGCDateStamps

-XX:+PrintGCDetails

-Xloggc:/opt/lucky/app/lucky/tomcat/logs/gc.log

上述這樣的配置,基本上可以達到:系統響應時間增快、JVM回收速度增快同時又不影響系統的響應率、JVM內存最大化利用、線程阻塞情況最小化。

Tomcat啟動慢調整
JVM環境中解決:

打開vi $JAVA_HOME/jre/lib/security/java.security這個文件,找到下面的內容:

securerandom.source=file:/dev/urandom

替換成

securerandom.source=file:/dev/./urandom

代碼模塊進行

數據庫查詢語句進行

參考:

JVM調優總結 -Xms -Xmx -Xmn -Xss

http://unixboy.iteye.com/blog/174173


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM