測試環(huán)境: OS: Ubuntu14.04 64位 (運行在Docker1.9) CPU: Intel i3 雙核四線程 Mem: 8G Tomcat版本: Tomcat8.5 Java SDK版本: JDK 8 測試軟件: Apache JMeter 2.8 測試說明: 測試代碼為接受一個http請求,返回一個String變量s. 該變量初始化為””, 循環(huán)10000次,每次添加內容”test\n” public class Test extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{ StringBuffer ret = new StringBuffer(); for(int i=0;i < 10000;="" i++)="" {="" ret.append(string.valueof(i)="" +="" '="" test\n');="" }="" printwriter="" printwriter="response.getWriter();" printwriter.println(ret);=""> 采用JMeter模擬5000個(用戶),在10s內對該接口不斷發(fā)起Get請求,并循環(huán)10次. 最后統(tǒng)計結果. 對每個配置的修改都會關閉并重啟tomcat 調優(yōu)方式一 : 修改…/bin/catalina.sh(啟動時優(yōu)化) Windows下為catalina.bat export JAVA_OPTS=”-server”
- 作用:tomcat默認以java –client方式運行, 添加”server”參數(shù)將tomcat切換為生產模式,使得tomcat能支持更高的并發(fā)數(shù)和吞吐量.
- 測試結果:
- 修改前:
- 總結:
- 最大并發(fā)數(shù)和吞吐量有明顯的提升.
- 添加參數(shù):
export JAVA_OPTS=”-server -Xms256M -Xmx256M”
- 作用:Xms參數(shù)表示初始堆的大小,也是堆大小的最小值,,默認值是總共的物理內存1/64, 且小于1G(下面是-Xmx同), Xmx參數(shù)表示堆的最大值.在本機中這個參數(shù)的值大約為128m.這里將其擴大一倍.正常情況下應當將這個參數(shù)的數(shù)值設置為相同.還有另外一些參數(shù),如Xss,表示每個線程的棧內存,默認為1M,但經過查閱資料表明這些參數(shù)一般情況下不需要改動.即增加堆內存是提高tomcat內存性能最好最安全的做法.
- 測試結果:
- 總結:
- 對比上個參數(shù),可以明顯看到并發(fā)請求的平均值,中值都有2-3倍的提升,最大值和吞吐率出現(xiàn)了下降.個人猜測吞吐率的下降是因為在吞吐量一定的情況下,每秒并發(fā)數(shù)的提高拉低了該數(shù)值.并發(fā)最大值的降低,平均值的升高表明在此配置下系統(tǒng)的處理能力已經有了提高,并且穩(wěn)定性也得到提升.
- 添加參數(shù):
export JAVA_OPTS=”-server -Xms512M -Xmx512M”
- 作用: 在上條參數(shù)的基礎上,將堆內存起始值和最大值都提高一倍
- 測試結果:
- 總結:
- 并發(fā)平均數(shù)和吞吐率變化不大,但并發(fā)最大值提升2倍左右.
- 測試代碼按最少的字節(jié)算,處理單個用戶請求需要50000bytes,在本測試中模擬的用戶數(shù)是5000,即使5000用戶并發(fā)處理,所需內存也只在200MB這個級別,所以堆內存設置為512MB與256MB,某些數(shù)據(jù)項可能已經遇到瓶頸.
- 添加參數(shù):
export JAVA_OPTS=”-server -Xms512M -Xmx512M -XX:+AggressiveOpts”
- 作用: -XX:+AggressiveOpts表示每當JDK版本升級時,你的JVM都會使用最新加入的優(yōu)化技術(如果有的話).建議加上,但也要注意若升級JDK版本后系統(tǒng)出現(xiàn)意外情況,應該對該參數(shù)的影響進行測試.
- 添加參數(shù):
export JAVA_OPTS=”-server -Xms512M -Xmx512M -XX:+AggressiveOpts -XX:+UseBiasedLocking”
- 作用: 啟用一個優(yōu)化的線程鎖.對于tomcat來說,每個http請求都會啟用線程,啟動該線程鎖可以讓tomcat對線程進行最優(yōu)調配.
- 測試結果:
- 總結:
- 除了吞吐率其他都降得很厲害.個人猜測因為本次測試代碼并不復雜,如果是執(zhí)行復雜的業(yè)務邏輯可能優(yōu)化效果會比較明顯,尤其是設計到當業(yè)務的計算量相差較大時.
- 添加參數(shù):
export JAVA_OPTS=”-server -Xms512M -Xmx512M -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC”
- 作用: 禁止顯示調用System.gc().若在代碼中顯示調用System.gc()讓JVM進行垃圾回收,會極大降低系統(tǒng)響應時間.
調優(yōu)方式二: 更改…/confrver.xml (容器內優(yōu)化) 在server.xml內定位到標簽,以下的內容均值在該標簽中修改內容 URIEncoding=”UTF-8”
- 作用: 使得tomcat可以解析含有中文名的文件的url
- 添加參數(shù)
protocol=”org.apache.coyote.http11.Http11Nio2Protocol” 若tomcat為8可改為上面的參數(shù),若為tomcat6建議改為”org.apache.coyote.http11.Http11NioProtocol”
enableLookups=”false”
acceptCount=”1000”
- 指定當所有可以使用的處理請求的線程數(shù)都被使用時,,可以放到處理隊列中的請求數(shù),,超過這個數(shù)的請求將不予處理,默認設置 100.這里設置為1000
- 添加參數(shù)
maxThreads=”5000”
- 最大并發(fā)數(shù),,默認設置 200,這里設置為JMeter中的模擬請求數(shù)5000
- 測試結果:
- 將上述幾個參數(shù)添加去本機的配置文件中,測試數(shù)據(jù)沒有明顯差距,故不貼出.
- 可能因為測試用例簡單,在這方面進行優(yōu)化有點殺雞焉用牛刀了.
總結 - 在本測試中,堆內存的更改對tomcat的優(yōu)化效果非常明顯.其實這是屬于JVM優(yōu)化的范疇,只不過作用于tomcat身上.
- 其他參數(shù)的優(yōu)化在本測試中效果不明顯,但我相信對于業(yè)務復雜的場景,這些優(yōu)化都是非常必要的,尤其是對server.xml的優(yōu)化.
- 另外,測試過程中出現(xiàn)讓我很費解的事.相同的配置運行多次,得到的數(shù)據(jù)會有較大的出入.比如我晚上測試了一邊.第二天起來用該配置再測一邊,得到的數(shù)據(jù)會同比波動會非常大.
- 結合多次實驗,發(fā)現(xiàn)數(shù)據(jù)的波動會出現(xiàn)在物理機和Docker容器的喚醒,重新打開JMeter軟件等行為之后,這些行為都會導致內存使用率的大量變化,這些都導致JVM的運行環(huán)境不夠穩(wěn)定,
- 所以,該測試的結果并不嚴謹,僅可作為參考而不可盡信.務必在您的環(huán)境親自測試一遍.
參考配置 catalina.sh export JAVA_OPTS=”-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true “
server.xml [objc] view plain copy - Connectorport='8080'
- protocol='org.apache.coyote.http11.Http11Nio2Protocol'
- connectionTimeout='20000'
- redirectPort='8443'
- enableLookups='false'
- acceptCount='100'
- maxThreads='200'
- minSpareThreads='10'
- compression='on'
- compressionMinSize='2048'
- compressableMimeType='text/html,text/xml,text/plain,text/css,text/javascript,application/javascript'
- URIEncoding='utf-8'
|