Java Web之Tomcat調優

Tomcat調優是一個老話題,目的都是為了提高站點的吞吐和并發。這里面涉及到Tomcat本身參數的優化和JVM優化。近期在研究JVM的參數設置和Tomcat集群,所以進行了一下調優實踐。需要說明的是:本文的配置肯定不是最好的,僅僅是一次實踐和一次記錄。步驟可以參考,但參數設置需要針對不同需求的項目來進行調整。

1、安裝APR(Apache Portable Runtime)

Tomcat 7 以后 Connector 默認啟用 APR 協議,但是只有配置了 APR庫才可以生效,否則還是會使用 BIO 或者NIO方式。如何配置?可以直接去http://tomcat.apache.org/download-native.cgi下載,里面有32bit和64bit兩種庫,本人是64位機器,所以將x64文件夾下的兩個文件tcnative-1.dlltcnative-1-src.pdb拷貝到Tomcat的bin目錄下,然后啟動 Tomcat,如果有如圖所示的輸出,說明配置成功。

安裝Apr后啟動狀態變化.PNG

為什么使用Apr?

官方如是說(翻譯了一下):Tomcat 可以使用 APR 來提供出色的可伸縮性,性能以及與原生服務器技術的更好集成。APR 有許多用途,提供了包括對高級IO功能操作系統級功能和本地進程處理的訪問。這些功能使得Tomcat成為一個通用的網絡服務器,能夠更好地與其他本地網絡技術進行整合,并且使整個Java作為一個完整的web服務器平臺更加可行。

網上有人測試過,APR相比較BIO、NIO,在處理高并發時效率更高。

2、配置Executor,增加線程數,提高并發能力

打開server.xml,找到被注釋的一段

    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
            maxThreads="150" minSpareThreads="4"/>

修改成

    <Executor   name="tomcatThreadPool" 
                namePrefix="catalina-exec-"
                maxThreads="500"                 //Tomcat 使用線程來處理請求,該值表示 Tomcat 能創建的最大的線程數
                minSpareThreads="20"             //最小空閑線程數,Tomcat 啟動時的初始化的線程數,表示即使沒有人使用也開這么多空線程等待,默認值是 10。
                maxIdleTime="60000"/>            //當服務的線程數超過最大線程數時,超過maxIdleTime的線程會被殺死回收直到線程數降低到最大數以內

3、配置Connector,設置超時、上傳和緩存信息

同樣在server.xml中,修改端口號為 8080 的Connector如下

    <Connector  executor="tomcatThreadPool"     //指明上面的executor
                port="8080" 
                protocol="HTTP/1.1"
                URIEncoding="UTF-8"
                connectionTimeout="30000"       //網絡連接超時,設置為 0 表示永不超時。單位:毫秒
                enableLookups="false"           //是否反查域名,以返回遠程主機的主機名,取值為:true 或 false,如果設置為false,則直接返回IP地址,為了提高處理能力,應設置為 false
                disableUploadTimeout="false"    //上傳時是否使用超時機制
                connectionUploadTimeout="150000"http://上傳超時時間
                acceptCount="300"               //指定當所有可以使用的處理請求的線程數都被使用時,可傳入連接請求的最大隊列長度,超過這個數的請求將不予處理
                keepAliveTimeout="120000"       //長連接最大保持時間,表示在下次請求過來之前,Tomcat 保持該連接多久,-1 為不限制超時。單位:毫秒
                maxKeepAliveRequests="1"        //表示在服務器關閉之前,該連接最大支持的請求數。超過該請求數的連接也將被關閉,1表示禁用,-1表示不限制個數
                compression="on"                //是否對響應的數據進行 GZIP 壓縮,off:表示禁止壓縮;on:表示允許壓縮(文本將被壓縮)、force:表示所有情況下都進行壓縮,默認值為off
                compressionMinSize="2048"       //表示壓縮響應的最小值,只有當響應報文大小大于這個值的時候才會對報文進行壓縮,如果開啟了壓縮功能
                compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png" //壓縮類型,指定對哪些類型的文件進行數據壓縮。
                redirectPort="8443" />

4、打開catalina.bat,打開JAVA_OPTS 進行JVM設置

如何設置JVM?
1、集成開發環境下啟動并使用JVM,如eclipse需要修改根目錄文件eclipse.ini;
2、Windows服務器下安裝版Tomcat,可使用Tomcatw.exe工具(Tomcat目錄下)和直接修改注冊表兩種方式修改JVM參數;
3、Windows服務器解壓版Tomcat注冊Windows服務,方法同上;
4、解壓版本的Tomcat, 通過startup.bat啟動Tomcat加載配置的,在Tomcat的bin 下catalina.bat 文件內添加;
5、Linux服務器Tomcat設置JVM,修改TOMCAT_HOME/bin/catalina.sh;

本人屬于第4種,所以打開catalina.bat,在第二行添加如下信息

set JAVA_OPTS=-server -Xms4G -Xmx4G -Xss512k

5、檢測設置是否生效

在設置之前,訪問Tomcat首頁,點擊Server Status查看相關信息

未優化之前的信息.png

優化以后,再次訪問查看,很明顯發生了很大變化


優化之后的信息.png

參考文獻

1、http://blog.csdn.net/centre10/article/details/50639693
2、http://blog.csdn.net/ldx891113/article/details/51735171

附錄:JVM常用參數詳解(網絡摘錄)

-server:一定要作為第一個參數,在多個 CPU 時性能佳,還有一種叫 -client 的模式,特點是啟動速度比較快,但運行時性能和內存管理效率不高,通常用于客戶端應用程序或開發調試,在 32 位環境下直接運行 Java 程序默認啟用該模式。Server 模式的特點是啟動速度比較慢,但運行時性能和內存管理效率很高,適用于生產環境,在具有 64 位能力的 JDK 環境下默認啟用該模式,可以不配置該參數。

-Xms:表示 Java 初始化堆的大小,-Xms 與-Xmx 設成一樣的值,避免 JVM 反復重新申請內存,導致性能大起大落,默認值為物理內存的 1/64,默認(MinHeapFreeRatio參數可以調整)空余堆內存小于 40% 時,JVM 就會增大堆直到 -Xmx 的最大限制。

-Xmx:表示最大 Java 堆大小,當應用程序需要的內存超出堆的最大值時虛擬機就會提示內存溢出,并且導致應用服務崩潰,因此一般建議堆的最大值設置為可用內存的最大值的80%。如何知道我的 JVM 能夠使用最大值,使用 java -Xmx512M -version 命令來進行測試,然后逐漸的增大 512 的值,如果執行正常就表示指定的內存大小可用,否則會打印錯誤信息,默認值為物理內存的 1/4,默認(MinHeapFreeRatio參數可以調整)空余堆內存大于 70% 時,JVM 會減少堆直到-Xms 的最小限制。

-Xss:表示每個 Java 線程堆棧大小,JDK 5.0 以后每個線程堆棧大小為 1M,以前每個線程堆棧大小為 256K。根據應用的線程所需內存大小進行調整,在相同物理內存下,減小這個值能生成更多的線程,但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在 3000~5000 左右。一般小的應用, 如果棧不是很深, 應該是128k 夠用的,大的應用建議使用 256k 或 512K,一般不易設置超過 1M,要不然容易出現out ofmemory。這個選項對性能影響比較大,需要嚴格的測試。

-XX:NewSize:設置新生代內存大小。

-XX:MaxNewSize:設置最大新生代新生代內存大小
-XX:PermSize:設置持久代內存大小

-XX:MaxPermSize:設置最大值持久代內存大小,永久代不屬于堆內存,堆內存只包含新生代和老年代。

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

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

-XX:+DisableExplicitGC:在 程序代碼中不允許有顯示的調用“System.gc()”。每次在到操作結束時手動調用 System.gc() 一下,付出的代價就是系統響應時間嚴重降低,就和關于 Xms,Xmx 里的解釋的原理一樣,這樣去調用 GC 導致系統的 JVM 大起大落。

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

-XX:+UseParNewGC:對新生代采用多線程并行回收,這樣收得快,注意最新的 JVM 版本,當使用 -XX:+UseConcMarkSweepGC 時,-XX:UseParNewGC 會自動開啟。因此,如果年輕代的并行 GC 不想開啟,可以通過設置 >-XX:-UseParNewGC 來關掉。

-XX:MaxTenuringThreshold:設置垃圾最大年齡。如果設置為0的話,則新生代對象不經過 Survivor 區,直接進入老年代。對于老年代比較多的應用(需要大量常駐內存的應用),可以提高效率。如果將此值設置為一 個較大值,則新生代對象會在 Survivor 區進行多次復制,這樣可以增加對象在新生代的存活時間,增加在新生代即被回收的概率,減少Full GC的頻率,這樣做可以在某種程度上提高服務穩定性。該參數只有在串行 GC 時才有效,這個值的設置是根據本地的 jprofiler 監控后得到的一個理想的值,不能一概而論原搬照抄。

-XX:+CMSParallelRemarkEnabled:在使用 UseParNewGC 的情況下,盡量減少 mark 的時間。

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

-XX:LargePageSizeInBytes:指定 Java heap 的分頁頁面大小,內存頁的大小不可設置過大, 會影響 Perm 的大小。

-XX:+UseFastAccessorMethods:使用 get,set 方法轉成本地代碼,原始類型的快速優化。
-XX:+UseCMSInitiatingOccupancyOnly:只有在 oldgeneration 在使用了初始化的比例后 concurrent collector 啟動收集。

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

-Xmn:新生代的內存空間大小,注意:此處的大小是(eden+ 2 survivor space)。與 jmap -heap 中顯示的 New gen 是不同的。整個堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保證堆大小不變的情況下,增大新生代后,將會減小老生代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的 3/8。

-XX:CMSInitiatingOccupancyFraction:當堆滿之后,并行收集器便開始進行垃圾收集,例如,當沒有足夠的空間來容納新分配或提升的對象。對于 CMS 收集器,長時間等待是不可取的,因為在并發垃圾收集期間應用持續在運行(并且分配對象)。因此,為了在應用程序使用完內存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先啟動。因為不同的應用會有不同對象分配模式,JVM 會收集實際的對象分配(和釋放)的運行時數據,并且分析這些數據,來決定什么時候啟動一次 CMS 垃圾收集周期。這個參數設置有很大技巧,基本上滿足(Xmx-Xmn)(100-CMSInitiatingOccupancyFraction)/100 >= Xmn 就不會出現 promotion failed。例如在應用中 Xmx 是6000,Xmn 是 512,那么 Xmx-Xmn 是 5488M,也就是老年代有 5488M,CMSInitiatingOccupancyFraction=90 說明老年代到 90% 滿的時候開始執行對老年代的并發垃圾回收(CMS),這時還 剩 10% 的空間是 548810% = 548M,所以即使 Xmn(也就是新生代共512M)里所有對象都搬到老年代里,548M 的空間也足夠了,所以只要滿足上面的公式,就不會出現垃圾回收時的 promotion failed,因此這個參數的設置必須與 Xmn 關聯在一起。

-XX:+CMSIncrementalMode:該標志將開啟 CMS 收集器的增量模式。增量模式經常暫停 CMS 過程,以便對應用程序線程作出完全的讓步。因此,收集器將花更長的時間完成整個收集周期。因此,只有通過測試后發現正常 CMS 周期對應用程序線程干擾太大時,才應該使用增量模式。由于現代服務器有足夠的處理器來適應并發的垃圾收集,所以這種情況發生得很少,用于但 CPU情況。

-XX:NewRatio:年輕代(包括 Eden 和兩個 Survivor 區)與年老代的比值(除去持久代),-XX:NewRatio=4 表示年輕代與年老代所占比值為 1:4,年輕代占整個堆棧的 1/5,Xms=Xmx 并且設置了 Xmn 的情況下,該參數不需要進行設置。

-XX:SurvivorRatio:Eden 區與 Survivor 區的大小比值,設置為 8,表示 2 個 Survivor 區(JVM 堆內存年輕代中默認有 2 個大小相等的 Survivor 區)與 1 個 Eden 區的比值為 2:8,即 1 個 Survivor 區占整個年輕代大小的 1/10。

-XX:+UseSerialGC:設置串行收集器。

-XX:+UseParallelGC:設置為并行收集器。此配置僅對年輕代有效。即年輕代使用并行收集,而年老代仍使用串行收集。

-XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集,JDK6.0 開始支持對年老代并行收集。

-XX:ConcGCThreads:早期 JVM 版本也叫-XX:ParallelCMSThreads,定義并發 CMS 過程運行時的線程數。比如 value=4 意味著 CMS 周期的所有階段都以 4 個線程來執行。盡管更多的線程會加快并發 CMS 過程,但其也會帶來額外的同步開銷。因此,對于特定的應用程序,應該通過測試來判斷增加 CMS 線程數是否真的能夠帶來性能的提升。如果還標志未設置,JVM 會根據并行收集器中的 -XX:ParallelGCThreads 參數的值來計算出默認的并行 CMS 線程數。

-XX:ParallelGCThreads:配置并行收集器的線程數,即:同時有多少個線程一起進行垃圾回收,此值建議配置與 CPU 數目相等。

-XX:OldSize:設置 JVM 啟動分配的老年代內存大小,類似于新生代內存的初始大小 -XX:NewSize。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容