1.Tomcat的優(yōu)化分成兩塊:
Tomcat啟動命令行中的優(yōu)化參數(shù)即JVM優(yōu)化
Tomcat容器自身參數(shù)的優(yōu)化
2. Tomcat啟動行參數(shù)的優(yōu)化
Tomcat 的啟動參數(shù)位于tomcat的安裝目錄\bin目錄下,如果你是Linux操作系統(tǒng)就是catalina.sh文件,如果你是Windows操作系統(tǒng)那么 你需要改動的就是catalina.bat文件。打開該文件,一般該文件頭部是一堆的由##包裹著的注釋文字,找到注釋文字的最后一段如:

敲入一個(gè)回車,加入如下的參數(shù)
Linux系統(tǒng)中tomcat的啟動參數(shù)
具體情況具體分析,每臺機(jī)子的參數(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
我不管你什么理由,只要你的tomcat是運(yùn)行在生產(chǎn)環(huán)境中的,這個(gè)參數(shù)必須給我加上
因?yàn)閠omcat默認(rèn)是以一種叫java –client的模式來運(yùn)行的,server即意味著你的tomcat是以真實(shí)的production的模式在運(yùn)行的,這也就意味著你的tomcat以 server模式運(yùn)行時(shí)將擁有:更大、更高的并發(fā)處理能力,更快更強(qiáng)捷的JVM垃圾回收機(jī)制,可以獲得更多的負(fù)載與吞吐量。。。更。。。還有更。。。
-Xms–Xmx
即JVM內(nèi)存設(shè)置了,把Xms與Xmx兩個(gè)值設(shè)成一樣是最優(yōu)的做法
–Xmn
設(shè)置年輕代大小為512m。整個(gè)堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個(gè)堆的3/8。
-Xss
是指設(shè)定每個(gè)線程的堆棧大小。這個(gè)就要依據(jù)你的程序,看一個(gè)線程 大約需要占用多少內(nèi)存,可能會有多少線程同時(shí)運(yùn)行等。一般不易設(shè)置超過1M,要不然容易出現(xiàn)out ofmemory。
-XX:+AggressiveOpts
作用如其名(aggressive),啟用這個(gè)參數(shù),則每當(dāng)JDK版本升級時(shí),你的JVM都會使用最新加入的優(yōu)化技術(shù)(如果有的話)
-XX:+UseBiasedLocking
啟用一個(gè)優(yōu)化了的線程鎖,我們知道在我們的appserver,每個(gè)http請求就是一個(gè)線程,有的請求短有的請求長,就會有請求排隊(duì)的現(xiàn)象,甚至還會出現(xiàn)線程阻塞,這個(gè)優(yōu)化了的線程鎖使得你的appserver內(nèi)對線程處理自動進(jìn)行最優(yōu)調(diào)配。
-XX:PermSize=128M-XX:MaxPermSize=256M
JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值,默認(rèn)是物理內(nèi)存的1/64;
在數(shù)據(jù)量的很大的文件導(dǎo)出時(shí),一定要把這兩個(gè)值設(shè)置上,否則會出現(xiàn)內(nèi)存溢出的錯(cuò)誤。
由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認(rèn)是物理內(nèi)存的1/4。
那么,如果是物理內(nèi)存4GB,那么64分之一就是64MB,這就是PermSize默認(rèn)值,也就是永生代內(nèi)存初始大小;
四分之一是1024MB,這就是MaxPermSize默認(rèn)大小。
-XX:+DisableExplicitGC
在 程序代碼中不允許有顯示的調(diào)用”System.gc()”??吹竭^有兩個(gè)極品工程中每次在DAO操作結(jié)束時(shí)手動調(diào)用System.gc()一下,覺得這樣 做好像能夠解決它們的out ofmemory問題一樣,付出的代價(jià)就是系統(tǒng)響應(yīng)時(shí)間嚴(yán)重降低,就和我在關(guān)于Xms,Xmx里的解釋的原理一樣,這樣去調(diào)用GC導(dǎo)致系統(tǒng)的JVM大起大 落,性能不到什么地方去喲!
-XX:+UseParNewGC
對年輕代采用多線程并行回收,這樣收得快。
-XX:+UseConcMarkSweepGC
即CMS gc,這一特性只有jdk1.5即后續(xù)版本才具有的功能,它使用的是gc估算觸發(fā)和heap占用觸發(fā)。
我們知道頻頻繁的GC會造面JVM的大起大落從而影響到系統(tǒng)的效率,因此使用了CMS GC后可以在GC次數(shù)增多的情況下,每次GC的響應(yīng)時(shí)間卻很短,比如說使用了CMS GC后經(jīng)過jprofiler的觀察,GC被觸發(fā)次數(shù)非常多,而每次GC耗時(shí)僅為幾毫秒。
-XX:MaxTenuringThreshold
設(shè) 置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進(jìn)入年老代。對于年老代比較多的應(yīng)用,可以提高效率。如果將此值設(shè)置為一 個(gè)較大值,則年輕代對象會在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象再年輕代的存活時(shí)間,增加在年輕代即被回收的概率。
這個(gè)值的設(shè)置是根據(jù)本地的jprofiler監(jiān)控后得到的一個(gè)理想的值,不能一概而論原搬照抄。
-XX:+CMSParallelRemarkEnabled
在使用UseParNewGC 的情況下, 盡量減少 mark 的時(shí)間
-XX:+UseCMSCompactAtFullCollection
在使用concurrent gc 的情況下, 防止 memoryfragmention, 對live object 進(jìn)行整理, 使 memory 碎片減少。
-XX:LargePageSizeInBytes
指定 Java heap的分頁頁面大小
-XX:+UseFastAccessorMethods
get,set 方法轉(zhuǎn)成本地代碼
-XX:+UseCMSInitiatingOccupancyOnly
指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 啟動收集
-XX:CMSInitiatingOccupancyFraction=70
CMSInitiatingOccupancyFraction,這個(gè)參數(shù)設(shè)置有很大技巧,基本上滿足(Xmx-Xmn)(100- CMSInitiatingOccupancyFraction)/100>=Xmn就 不會出現(xiàn)promotion failed。在我的應(yīng)用中Xmx是6000,Xmn是512,那么Xmx-Xmn是5488兆,也就是年老代有5488
兆,CMSInitiatingOccupancyFraction=90說明年老代到90%滿的時(shí)候開始執(zhí)行對年老代的并發(fā)垃圾回收(CMS),這時(shí)還 剩10%的空間是548810%=548兆,所以即使Xmn(也就是年輕代共512兆)里所有對象都搬到年老代里,548兆的空間也足夠了,所以只要滿 足上面的公式,就不會出現(xiàn)垃圾回收時(shí)的promotion failed;
因此這個(gè)參數(shù)的設(shè)置必須與Xmn關(guān)聯(lián)在一起。
-Djava.awt.headless=true
這 個(gè)參數(shù)一般我們都是放在最后使用的,這全參數(shù)的作用是這樣的,有時(shí)我們會在我們的J2EE工程中使用一些圖表工具如:jfreechart,用于在web 網(wǎng)頁輸出GIF/JPG等流,在winodws環(huán)境下,一般我們的app server在輸出圖形時(shí)不會碰到什么問題,但是在linux/unix環(huán)境下經(jīng)常會碰到一個(gè)exception導(dǎo)致你在winodws開發(fā)環(huán)境下圖片顯 示的好好可是在linux/unix下卻顯示不出來,因此加上這個(gè)參數(shù)以免避這樣的情況出現(xiàn)。
3.Tomcat容器內(nèi)的優(yōu)化
前面我們對Tomcat啟動時(shí)的命令進(jìn)行了優(yōu)化,增加了系統(tǒng)的JVM可使用數(shù)、垃圾回收效率與線程阻塞情況、增加了系統(tǒng)響應(yīng)效率等還有一個(gè)很重要的指標(biāo),我們沒有去做優(yōu)化,就是吞吐量。
還記得學(xué)習(xí)中說的,這個(gè)系統(tǒng)本身可以處理1000,你沒有優(yōu)化和配置導(dǎo)致它默認(rèn)只能處理25。因此下面我們來看Tomcat容器內(nèi)的優(yōu)化。
打開tomcat安裝目錄\conf\server.xml文件,定位到這一行:
<connector port="8080" protocol="HTTP/1.1" <="" p="" style="word-wrap: break-word;">
這一行就是我們的tomcat容器性能參數(shù)設(shè)置的地方,它一般都會有一個(gè)默認(rèn)值,這些默認(rèn)值是遠(yuǎn)遠(yuǎn)不夠我們的使用的,我們來看經(jīng)過更改后的這一段的配置:
<connector port="8080" protocol="HTTP/1.1" <="" p="" style="word-wrap: break-word;">
URIEncoding="UTF-8"
minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
disableUploadTimeout="true"
connectionTimeout="20000"
acceptCount="300"
maxThreads="300"
maxProcessors="1000"
minProcessors="5"
useURIValidationHack="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
redirectPort="8443"
/>
URIEncoding=”UTF-8”
使得tomcat可以解析含有中文名的文件的url,真方便,不像apache里還有搞個(gè)mod_encoding,還要手工編譯
maxSpareThreads
maxSpareThreads 的意思就是如果空閑狀態(tài)的線程數(shù)多于設(shè)置的數(shù)目,則將這些線程中止,減少這個(gè)池中的線程總數(shù)。
minSpareThreads
最小備用線程數(shù),tomcat啟動時(shí)的初始化的線程數(shù)。
enableLookups
這個(gè)功效和Apache中的HostnameLookups一樣,設(shè)為關(guān)閉。
connectionTimeout
connectionTimeout為網(wǎng)絡(luò)連接超時(shí)時(shí)間毫秒數(shù)。
maxThreads
maxThreads Tomcat使用線程來處理接收的每個(gè)請求。這個(gè)值表示Tomcat可創(chuàng)建的最大的線程數(shù),即最大并發(fā)數(shù)。
acceptCount
acceptCount是當(dāng)線程數(shù)達(dá)到maxThreads后,后續(xù)請求會被放入一個(gè)等待隊(duì)列,這個(gè)acceptCount是這個(gè)隊(duì)列的大小,如果這個(gè)隊(duì)列也滿了,就直接refuse connection
maxProcessors與minProcessors
在 Java中線程是程序運(yùn)行時(shí)的路徑,是在一個(gè)程序中與其它控制線程無關(guān)的、能夠獨(dú)立運(yùn)行的代碼段。它們共享相同的地址空間。多線程幫助程序員寫出CPU最 大利用率的高效程序,使空閑時(shí)間保持最低,從而接受更多的請求。
通常Windows是1000個(gè)左右,Linux是2000個(gè)左右。
useURIValidationHack
我們來看一下tomcat中的一段源碼:
security
if (connector.getUseURIValidationHack()) {
String uri = validate(request.getRequestURI());
if (uri == null) {
res.setStatus(400);
res.setMessage("Invalid URI");
throw new IOException("Invalid URI");
} else {
req.requestURI().setString(uri);
// Redoing the URI decoding
req.decodedURI().duplicate(req.requestURI());
req.getURLDecoder().convert(req.decodedURI(), true);
}
}
可以看到如果把useURIValidationHack設(shè)成"false",可以減少它對一些url的不必要的檢查從而減省開銷。
enableLookups=“false”
為了消除DNS查詢對性能的影響我們可以關(guān)閉DNS查詢,方式是修改server.xml文件中的enableLookups參數(shù)值。
disableUploadTimeout
類似于Apache中的keeyalive一樣
HTTP 壓縮可以大大提高瀏覽網(wǎng)站的速度,它的原理是,在客戶端請求網(wǎng)頁后,從服務(wù)器端將網(wǎng)頁文件壓縮,再下載到客戶端,由客戶端的瀏覽器負(fù)責(zé)解壓縮并瀏覽。相對 于普通的瀏覽過程HTML,CSS,Javascript , Text ,它可以節(jié)省40%左右的流量。更為重要的是,它可以對動態(tài)生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等輸出的網(wǎng)頁也能進(jìn)行壓縮,壓縮效率驚人。
1)compression=“on” 打開壓縮功能
2)compressionMinSize=“2048” 啟用壓縮的輸出內(nèi)容大小,這里面默認(rèn)為2KB
3)noCompressionUserAgents=“gozilla, traviata” 對于以下的瀏覽器,不啟用壓縮
4)compressableMimeType=“text/html,text/xml” 壓縮類型
最后不要忘了把8443端口的地方也加上同樣的配置,因?yàn)槿绻覀冏遠(yuǎn)ttps協(xié)議的話,我們將會用到8443端口這個(gè)段的配置,對吧?
<connector port="8443" protocol="HTTP/1.1" <="" p="" style="word-wrap: break-word;">
URIEncoding="UTF-8" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true" connectionTimeout="20000"
acceptCount="300" maxThreads="300" maxProcessors="1000" minProcessors="5"
useURIValidationHack="false"
compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
SSLEnabled="true"
scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="d:/tomcat2/conf/shnlap93.jks" keystorePass="aaaaaa"
/>