天天看點

linux環境下的tomcat8.0的記憶體優化配置及垃圾回收管理等系列優化措施

Tomcat8 安全配置與性能優化

部落格分類: java架構

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等,具體監控及分析方式去網上搜尋即可。

叢集方案

單個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可以組合使用,具體場景具體分析吧~

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:打開對年老代的壓縮。可能會影響性能,但是可以消除碎片

在記憶體設定中需要做一下權衡

1)記憶體越大,一般情況下處理的效率也越高,但同時在做垃圾回收的時候所需要的時間也就越長,在這段時間内的處理效率是必然要受影響的。

2)在大多數的網絡文章中都推薦 Xmx和Xms設定為一緻,說是避免頻繁的回收,這個在測試的時候沒有看到明顯的效果,記憶體的占用情況基本都是鋸齒狀的效果,是以這個還要根據實際情況來定。

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.配置示例

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>

管理AJP端口

AJP是為 Tomcat 與 HTTP 伺服器之間通信而定制的協定,能提供較高的通信速度和效率。如果tomcat前端放的是apache的時候,會使用到AJP這個連接配接器。由于我們公司前端是由nginx做的反向代理,是以不使用此連接配接器,是以需要登出掉該連接配接器。

<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

預設 Tomcat 是開啟了對war包的熱部署的。為了防止被植入×××等惡意程式,是以我們要關閉自動部署。

修改執行個體:

http://blog.csdn.net/wanglei_storage/article/details/50225779