(轉)Tomcat調優

問題定位

對於Tomcat的處理耗時較長的問題主要有當時的併發量、session數、內存及內存的回收等幾個方面形成的。出現問題以後就要進行分析了。 

1.關於Tomcat的session數目 
這個能夠直接從Tomcat的web管理界面去查看便可 
或者藉助於第三方工具Lambda Probe來查看,它相對於Tomcat自帶的管理稍微多了點功能,但也很少 

2.監視Tomcat的內存使用狀況 
使用JDK自帶的jconsole能夠比較明瞭的看到內存的使用狀況,線程的狀態,當前加載的類的總量等 
JDK自帶的jvisualvm能夠下載插件(如GC等),能夠查看更豐富的信息。若是是分析本地的Tomcat的話,還能夠進行內存抽樣等,檢查每一個類的使用狀況 

3.打印類的加載狀況及對象的回收狀況 
這個能夠經過配置JVM的啓動參數,打印這些信息(到屏幕(默認也會到catalina.log中)或者文件),具體參數以下: 
-XX:+PrintGC:輸出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs] 
-XX:+PrintGCDetails:輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] 
-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可與上面兩個混合使用,輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] 
-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中斷的執行時間。可與上面混合使用。輸出形式:Application time: 0.5291524 seconds 
-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期間程序暫停的時間。可與上面混合使用。輸出形式:Total time for which application threads were stopped: 0.0468229 seconds 
-XX:PrintHeapAtGC: 打印GC先後的詳細堆棧信息 
-Xloggc:filename:與上面幾個配合使用,把相關日誌信息記錄到文件以便分析 

-verbose:class 監視加載的類的狀況 
-verbose:gc 在虛擬機發生內存回收時在輸出設備顯示信息 
-verbose:jni 輸出native方法調用的相關狀況,通常用於診斷jni調用錯誤信息 

4.添加JMS遠程監控 
對於部署在局域網內其它機器上的Tomcat,能夠打開JMX監控端口,局域網其它機器就能夠經過這個端口查看一些經常使用的參數(但一些比較複雜的功能不支持),一樣是在JVM啓動參數中配置便可,配置以下: 
-Dcom.sun.management.jmxremote.ssl=false  -Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=192.168.71.38 設置JVM的JMS監控監聽的IP地址,主要是爲了防止錯誤的監聽成127.0.0.1這個內網地址 
-Dcom.sun.management.jmxremote.port=1090 設置JVM的JMS監控的端口 
-Dcom.sun.management.jmxremote.ssl=false 設置JVM的JMS監控不實用SSL 
-Dcom.sun.management.jmxremote.authenticate=false 設置JVM的JMS監控不須要認證 


5.專業點的分析工具備 
IBM ISA,JProfiler等,具體監控及分析方式去網上搜索便可。 javascript

 

 

集羣方案

單個Tomcat的處理性能是有限的,當併發量較大的時候,就須要有部署多套來進行負載均衡了。 

集羣的關鍵點有如下幾點: 
1.引入負載端 
軟負載可使用nginx或者apache來進行,主要是使用一個分發的功能 
參考: 
http://ajita.iteye.com/blog/1715312(nginx負載) 
http://ajita.iteye.com/blog/1717121(apache負載) 

2.共享session處理 
目前的處理方式有以下幾種: 
1).使用Tomcat自己的Session複製功能 
參考http://ajita.iteye.com/blog/1715312(Session複製的配置) 
方案的有點是配置簡單,缺點是當集羣數量較多時,Session複製的時間會比較長,影響響應的效率 
2).使用第三方來存放共享Session 
目前用的較多的是使用memcached來管理共享Session,藉助於memcached-sesson-manager來進行Tomcat的Session管理 
參考http://ajita.iteye.com/blog/1716320(使用MSM管理Tomcat集羣session) 
3).使用黏性session的策略 
對於會話要求不太強(不涉及到計費,失敗了容許從新請求下等)的場合,同一個用戶的session能夠由nginx或者apache交給同一個Tomcat來處理,這就是所謂的session sticky策略,目前應用也比較多 
參考:http://ajita.iteye.com/blog/1848665(tomcat session sticky) 
nginx默認不包含session sticky模塊,須要從新編譯才行(windows下我也不知道怎麼從新編譯) 
優勢是處理效率高多了,缺點是強會話要求的場合不合適 

3.小結 
以上是實現集羣的要點,其中1和2能夠組合使用,具體場景具體分析吧~css

 

JVM優化

Tomcat自己仍是運行在JVM上的,經過對JVM參數的調整咱們可使Tomcat擁有更好的性能。針對JVM的優化目前主要在兩個方面: 

1.內存調優 
內存方式的設置是在catalina.sh中,調整一下JAVA_OPTS變量便可,由於後面的啓動參數會把JAVA_OPTS做爲JVM的啓動參數來處理。 

具體設置以下: 
JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4" 

其各項參數以下: 
-Xmx3550m:設置JVM最大可用內存爲3550M。 
-Xms3550m:設置JVM促使內存爲3550m。此值能夠設置與-Xmx相同,以免每次垃圾回收完成後JVM從新分配內存。 
-Xmn2g:設置年輕代大小爲2G。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代通常固定大小爲64m,因此增大年輕代後,將會減少年老代大小。此值對系統性能影響較大,Sun官方推薦配置爲整個堆的3/8。 
-Xss128k:設置每一個線程的堆棧大小。JDK5.0之後每一個線程堆棧大小爲1M,之前每一個線程堆棧大小爲256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減少這個值能生成更多的線程。可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右。 

-XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置爲4,則年輕代與年老代所佔比值爲1:4,年輕代佔整個堆棧的1/5 
-XX:SurvivorRatio=4:設置年輕代中Eden區與Survivor區的大小比值。設置爲4,則兩個Survivor區與一個Eden區的比值爲2:4,一個Survivor區佔整個年輕代的1/6 
-XX:MaxPermSize=16m:設置持久代大小爲16m。 
-XX:MaxTenuringThreshold=0:設置垃圾最大年齡。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代。對於年老代比較多的應用,能夠提升效率。若是將此值設置爲一個較大值,則年輕代對象會在Survivor區進行屢次複製,這樣能夠增長對象再年輕代的存活時間,增長在年輕代即被回收的概論。 


2.垃圾回收策略調優 
垃圾回收的設置也是在catalina.sh中,調整JAVA_OPTS變量。 
具體設置以下: 
JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100" 
具體的垃圾回收策略及相應策略的各項參數以下: 

串行收集器(JDK1.5之前主要的回收方式) 
-XX:+UseSerialGC:設置串行收集器 

並行收集器(吞吐量優先) 
示例: 
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 

-XX:+UseParallelGC:選擇垃圾收集器爲並行收集器。此配置僅對年輕代有效。即上述配置下,年輕代使用併發收集,而年老代仍舊使用串行收集。 
-XX:ParallelGCThreads=20:配置並行收集器的線程數,即:同時多少個線程一塊兒進行垃圾回收。此值最好配置與處理器數目相等。 
-XX:+UseParallelOldGC:配置年老代垃圾收集方式爲並行收集。JDK6.0支持對年老代並行收集 
-XX:MaxGCPauseMillis=100:設置每次年輕代垃圾回收的最長時間,若是沒法知足此時間,JVM會自動調全年輕代大小,以知足此值。 
-XX:+UseAdaptiveSizePolicy:設置此選項後,並行收集器會自動選擇年輕代區大小和相應的Survivor區比例,以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用並行收集器時,一直打開。 

併發收集器(響應時間優先) 
示例:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC 
-XX:+UseConcMarkSweepGC:設置年老代爲併發收集。測試中配置這個之後,-XX:NewRatio=4的配置失效了,緣由不明。因此,此時年輕代大小最好用-Xmn設置。 
-XX:+UseParNewGC: 設置年輕代爲並行收集。可與CMS收集同時使用。JDK5.0以上,JVM會根據系統配置自行設置,因此無需再設置此值。 
-XX:CMSFullGCsBeforeCompaction:因爲併發收集器不對內存空間進行壓縮、整理,因此運行一段時間之後會產生「碎片」,使得運行效率下降。此值設置運行多少次GC之後對內存空間進行壓縮、整理。 
-XX:+UseCMSCompactAtFullCollection:打開對年老代的壓縮。可能會影響性能,可是能夠消除碎片 

3.小結 
在內存設置中須要作一下權衡 
1)內存越大,通常狀況下處理的效率也越高,但同時在作垃圾回收的時候所須要的時間也就越長,在這段時間內的處理效率是必然要受影響的。 
2)在大多數的網絡文章中都推薦 Xmx和Xms設置爲一致,說是避免頻繁的回收,這個在測試的時候沒有看到明顯的效果,內存的佔用狀況基本都是鋸齒狀的效果,因此這個還要根據實際狀況來定。html

 

Server.xml的Connection優化

Tomcat的Connector是Tomcat接收HTTP請求的關鍵模塊,咱們能夠配置它來指定IO模式,以及處理經過這個Connector接受到的請求的處理線程數以及其它一些經常使用的HTTP策略。其主要配置參數以下: 

1.指定使用NIO模型來接受HTTP請求 
protocol="org.apache.coyote.http11.Http11NioProtocol" 指定使用NIO模型來接受HTTP請求。默認是BlockingIO,配置爲protocol="HTTP/1.1" 
acceptorThreadCount="2" 使用NIO模型時接收線程的數目 

2.指定使用線程池來處理HTTP請求 
首先要配置一個線程池來處理請求(與Connector是平級的,多個Connector可使用同一個線程池來處理請求) 
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 
maxThreads="1000" minSpareThreads="50" maxIdleTime="600000"/> 
<Connector port="8080"
executor="tomcatThreadPool" 指定使用的線程池 

3.指定BlockingIO模式下的處理線程數目 
maxThreads="150"//Tomcat使用線程來處理接收的每一個請求。這個值表示Tomcat可建立的最大的線程數。默認值200。能夠根據機器的時期性能和內存大小調整,通常能夠在400-500。最大能夠在800左右。 
minSpareThreads="25"---Tomcat初始化時建立的線程數。默認值4。若是當前沒有空閒線程,且沒有超過maxThreads,一次性建立的空閒線程數量。Tomcat初始化時建立的線程數量也由此值設置。 
maxSpareThreads="75"--一旦建立的線程超過這個值,Tomcat就會關閉再也不須要的socket線程。默認值50。一旦建立的線程超過此數值,Tomcat會關閉再也不須要的線程。線程數能夠大體上用 「同時在線人數*每秒用戶操做次數*系統平均操做時間」 來計算。 
acceptCount="100"----指定當全部可使用的處理請求的線程數都被使用時,能夠放處處理隊列中的請求數,超過這個數的請求將不予處理。默認值10。若是當前可用線程數爲0,則將請求放入處理隊列中。這個值限定了請求隊列的大小,超過這個數值的請求將不予處理。 
connectionTimeout="20000" --網絡鏈接超時,默認值20000,單位:毫秒。設置爲0表示永不超時,這樣設置有隱患的。一般可設置爲30000毫秒。 

4.其它經常使用設置 
maxHttpHeaderSize="8192" http請求頭信息的最大程度,超過此長度的部分不予處理。通常8K。 
URIEncoding="UTF-8" 指定Tomcat容器的URL編碼格式。 
disableUploadTimeout="true" 上傳時是否使用超時機制 
enableLookups="false"--是否反查域名,默認值爲true。爲了提升處理能力,應設置爲false 
compression="on"   打開壓縮功能 
compressionMinSize="10240" 啓用壓縮的輸出內容大小,默認爲2KB 
noCompressionUserAgents="gozilla, traviata"   對於如下的瀏覽器,不啓用壓縮 
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 哪些資源類型須要壓縮 

5.小結 
關於Tomcat的Nio和ThreadPool,自己的引入就提升了處理的複雜性,因此對於效率的提升有多少,須要實際驗證一下。 

6.配置示例 
<Connector port="8080" 
redirectPort="8443"
maxThreads="150" 
minSpareThreads="25" 
maxSpareThreads="75" 
acceptCount="100" 
connectionTimeout="20000" 
protocol="HTTP/1.1" 

maxHttpHeaderSize="8192" 
URIEncoding="UTF-8" 
disableUploadTimeout="true" 
enableLookups="false" 
compression="on" 
compressionMinSize="10240" 
noCompressionUserAgents="gozilla, traviata" 
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"> 
... 
</Connector>

 

 

轉自:http://www.cnblogs.com/kreo/p/4434802.htmljava

相關文章
相關標籤/搜索