Tomcat 的缺省配置是不能穩定長(cháng)期運行的,也就是不適合生產(chǎn)環(huán)境,它會(huì )死機,讓你不斷重新啟動(dòng),甚至在午夜時(shí)分喚醒你。對于操作系統優(yōu)化來(lái)說(shuō),是盡可能的增大可使用的內存容量、提高CPU 的頻率,保證文件系統的讀寫(xiě)速率等。經(jīng)過(guò)壓力測試驗證,在并發(fā)連接很多的情況下,CPU 的處理能力越強,系統運行速度越快。
Tomcat 的優(yōu)化不像其它軟件那樣,簡(jiǎn)簡(jiǎn)單單的修改幾個(gè)參數就可以了,它的優(yōu)化主要有三方面,分為系統優(yōu)化,Tomcat 本身的優(yōu)化,Java 虛擬機(JVM)調優(yōu)。系統優(yōu)化就不在介紹了,接下來(lái)就詳細的介紹一下 Tomcat 本身與 JVM 優(yōu)化,以 Tomcat 7 為例。
一、Tomcat 本身優(yōu)化
Tomcat 的自身參數的優(yōu)化,這塊很像 ApacheHttp Server。修改一下 xml 配置文件中的參數,調整最大連接數,超時(shí)等。此外,我們安裝 Tomcat 是,優(yōu)化就已經(jīng)開(kāi)始了。
1、工作方式選擇
為了提升性能,首先就要對代碼進(jìn)行動(dòng)靜分離,讓 Tomcat 只負責 jsp 文件的解析工作。如采用 Apache 和 Tomcat 的整合方式,他們之間的連接方案有三種選擇,JK、http_proxy 和 ajp_proxy。相對于 JK 的連接方式,后兩種在配置上比較簡(jiǎn)單的,靈活性方面也一點(diǎn)都不遜色。但就穩定性而言不像JK 這樣久經(jīng)考驗,所以建議采用 JK 的連接方式。
2、Connector 連接器的配置
之前文件介紹過(guò)的 Tomcat 連接器的三種方式: bio、nio 和 apr,三種方式性能差別很大,apr 的性能最優(yōu), bio 的性能最差。而 Tomcat 7 使用的 Connector 默認就啟用的 Apr 協(xié)議,但需要系統安裝 Apr 庫,否則就會(huì )使用 bio 方式。
3、配置文件優(yōu)化
配置文件優(yōu)化其實(shí)就是對 server.xml 優(yōu)化,可以提大大提高 Tomcat 的處理請求的能力,下面我們來(lái)看 Tomcat 容器內的優(yōu)化。
默認配置下,Tomcat 會(huì )為每個(gè)連接器創(chuàng )建一個(gè)綁定的線(xiàn)程池(最大線(xiàn)程數 200),服務(wù)啟動(dòng)時(shí),默認創(chuàng )建了 5 個(gè)空閑線(xiàn)程隨時(shí)等待用戶(hù)請求。
首先,打開(kāi) ${TOMCAT_HOME}/conf/server.xml,搜索【<Executor name="tomcatThreadPool"】,開(kāi)啟并調整為
1
2
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="500" minSpareThreads="20" maxSpareThreads="50" maxIdleTime="60000"/>
注意, Tomcat 7 在開(kāi)啟線(xiàn)程池前,一定要安裝好 Apr 庫,并可以啟用,否則會(huì )有錯誤報出,shutdown.sh 腳本無(wú)法關(guān)閉進(jìn)程。
然后,修改<Connector …>節點(diǎn),增加 executor 屬性,搜索【port="8080"】,調整為
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
URIEncoding="UTF-8"
connectionTimeout="30000"
enableLookups="false"
disableUploadTimeout="false"
connectionUploadTimeout="150000"
acceptCount="300"
keepAliveTimeout="120000"
maxKeepAliveRequests="1"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png"
redirectPort="8443" />
maxThreads :Tomcat 使用線(xiàn)程來(lái)處理接收的每個(gè)請求,這個(gè)值表示 Tomcat 可創(chuàng )建的最大的線(xiàn)程數,默認值是 200
minSpareThreads:最小空閑線(xiàn)程數,Tomcat 啟動(dòng)時(shí)的初始化的線(xiàn)程數,表示即使沒(méi)有人使用也開(kāi)這么多空線(xiàn)程等待,默認值是 10。
maxSpareThreads:最大備用線(xiàn)程數,一旦創(chuàng )建的線(xiàn)程超過(guò)這個(gè)值,Tomcat 就會(huì )關(guān)閉不再需要的 socket 線(xiàn)程。
上邊配置的參數,最大線(xiàn)程 500(一般服務(wù)器足以),要根據自己的實(shí)際情況合理設置,設置越大會(huì )耗費內存和 CPU,因為 CPU 疲于線(xiàn)程上下文切換,沒(méi)有精力提供請求服務(wù)了,最小空閑線(xiàn)程數 20,線(xiàn)程最大空閑時(shí)間 60 秒,當然允許的最大線(xiàn)程連接數還受制于操作系統的內核參數設置,設置多大要根據自己的需求與環(huán)境。當然線(xiàn)程可以配置在“tomcatThreadPool”中,也可以直接配置在“Connector”中,但不可以重復配置。
URIEncoding:指定 Tomcat 容器的 URL 編碼格式,語(yǔ)言編碼格式這塊倒不如其它 WEB 服務(wù)器軟件配置方便,需要分別指定。
connnectionTimeout: 網(wǎng)絡(luò )連接超時(shí),單位:毫秒,設置為 0 表示永不超時(shí),這樣設置有隱患的。通??稍O置為 30000 毫秒,可根據檢測實(shí)際情況,適當修改。
enableLookups: 是否反查域名,以返回遠程主機的主機名,取值為:true 或 false,如果設置為false,則直接返回IP地址,為了提高處理能力,應設置為 false。
disableUploadTimeout:上傳時(shí)是否使用超時(shí)機制。
connectionUploadTimeout:上傳超時(shí)時(shí)間,畢竟文件上傳可能需要消耗更多的時(shí)間,這個(gè)根據你自己的業(yè)務(wù)需要自己調,以使Servlet有較長(cháng)的時(shí)間來(lái)完成它的執行,需要與上一個(gè)參數一起配合使用才會(huì )生效。
acceptCount:指定當所有可以使用的處理請求的線(xiàn)程數都被使用時(shí),可傳入連接請求的最大隊列長(cháng)度,超過(guò)這個(gè)數的請求將不予處理,默認為100個(gè)。
keepAliveTimeout:長(cháng)連接最大保持時(shí)間(毫秒),表示在下次請求過(guò)來(lái)之前,Tomcat 保持該連接多久,默認是使用 connectionTimeout 時(shí)間,-1 為不限制超時(shí)。
maxKeepAliveRequests:表示在服務(wù)器關(guān)閉之前,該連接最大支持的請求數。超過(guò)該請求數的連接也將被關(guān)閉,1表示禁用,-1表示不限制個(gè)數,默認100個(gè),一般設置在100~200之間。
compression:是否對響應的數據進(jìn)行 GZIP 壓縮,off:表示禁止壓縮;on:表示允許壓縮(文本將被壓縮)、force:表示所有情況下都進(jìn)行壓縮,默認值為off,壓縮數據后可以有效的減少頁(yè)面的大小,一般可以減小1/3左右,節省帶寬。
compressionMinSize:表示壓縮響應的最小值,只有當響應報文大小大于這個(gè)值的時(shí)候才會(huì )對報文進(jìn)行壓縮,如果開(kāi)啟了壓縮功能,默認值就是2048。
compressableMimeType:壓縮類(lèi)型,指定對哪些類(lèi)型的文件進(jìn)行數據壓縮。
noCompressionUserAgents="gozilla, traviata": 對于以下的瀏覽器,不啟用壓縮。
如果已經(jīng)對代碼進(jìn)行了動(dòng)靜分離,靜態(tài)頁(yè)面和圖片等數據就不需要 Tomcat 處理了,那么也就不需要配置在 Tomcat 中配置壓縮了。
以上是一些常用的配置參數屬性,當然還有好多其它的參數設置,還可以繼續深入的優(yōu)化,HTTP Connector 與 AJP Connector 的參數屬性值,可以參考官方文檔的詳細說(shuō)明:
https://tomcat.apache.org/tomcat-7.0-doc/config/http.htmlhttps://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html二、JVM 優(yōu)化
Tomcat 啟動(dòng)命令行中的優(yōu)化參數,就是 JVM 的優(yōu)化 。Tomcat 首先跑在 JVM 之上的,因為它的啟動(dòng)其實(shí)也只是一個(gè) java 命令行,首先我們需要對這個(gè) JAVA 的啟動(dòng)命令行進(jìn)行調優(yōu)。不管是 YGC 還是 Full GC,GC 過(guò)程中都會(huì )對導致程序運行中中斷,正確的選擇不同的 GC 策略,調整 JVM、GC 的參數,可以極大的減少由于 GC 工作,而導致的程序運行中斷方面的問(wèn)題,進(jìn)而適當的提高 Java 程序的工作效率。但是調整 GC 是以個(gè)極為復雜的過(guò)程,由于各個(gè)程序具備不同的特點(diǎn),如:web 和 GUI 程序就有很大區別(Web可以適當的停頓,但GUI停頓是客戶(hù)無(wú)法接受的),而且由于跑在各個(gè)機器上的配置不同(主要 cup 個(gè)數,內存不同),所以使用的 GC 種類(lèi)也會(huì )不同。
1、JVM 參數配置方法
Tomcat 的啟動(dòng)參數位于安裝目錄 ${JAVA_HOME}/bin目錄下,Linux 操作系統就是 catalina.sh 文件。JAVA_OPTS,就是用來(lái)設置 JVM 相關(guān)運行參數的變量,還可以在 CATALINA_OPTS 變量中設置。關(guān)于這 2 個(gè)變量,還是多少有些區別的:
JAVA_OPTS:用于當 Java 運行時(shí)選項“start”、“stop”或“run”命令執行。
CATALINA_OPTS:用于當 Java 運行時(shí)選項“start”或“run”命令執行。
為什么有兩個(gè)不同的變量?它們之間都有什么區別呢?
首先,在啟動(dòng) Tomcat 時(shí),任何指定變量的傳遞方式都是相同的,可以傳遞到執行“start”或“run”命令中,但只有設定在 JAVA_OPTS 變量里的參數被傳遞到“stop”命令中。對于 Tomcat 運行過(guò)程,可能沒(méi)什么區別,影響的是結束程序,而不是啟動(dòng)程序。
第二個(gè)區別是更微妙,其他應用程序也可以使用 JAVA_OPTS 變量,但只有在 Tomcat 中使用 CATALINA_OPTS 變量。如果你設置環(huán)境變量為只使用 Tomcat,最好你會(huì )建議使用 CATALINA_OPTS 變量,而如果你設置環(huán)境變量使用其它的 Java 應用程序,例如 JBoss,你應該把你的設置放在JAVA_OPTS 變量中。
2、JVM 參數屬性
32 位系統下 JVM 對內存的限制:不能突破 2GB ,那么這時(shí)你的 Tomcat 要優(yōu)化,就要講究點(diǎn)技巧了,而在 64 位操作系統上無(wú)論是系統內存還是 JVM 都沒(méi)有受到 2GB 這樣的限制。
針對于 JMX 遠程監控也是在這里設置,以下為 64 位系統環(huán)境下的配置,內存加入的參數如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CATALINA_OPTS="
-server
-Xms6000M
-Xmx6000M
-Xss512k
-XX:NewSize=2250M
-XX:MaxNewSize=2250M
-XX:PermSize=128M
-XX:MaxPermSize=256M
-XX:+AggressiveOpts
-XX:+UseBiasedLocking
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=31
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:LargePageSizeInBytes=128m
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-Duser.timezone=Asia/Shanghai
-Djava.awt.headless=true"
為了看著(zhù)方便,將每個(gè)參數單獨寫(xiě)一行。上面參數好多啊,可能有人寫(xiě)到現在都沒(méi)見(jiàn)過(guò)一個(gè)在 Tomcat 的啟動(dòng)命令里加了這么多參數,當然,這些參數只是我機器上的,不一定適合你,尤其是參數后的 value(值)是需要根據你自己的實(shí)際情況來(lái)設置的。
上述這樣的配置,基本上可以達到:
系統響應時(shí)間增快;
JVM回收速度增快同時(shí)又不影響系統的響應率;
JVM內存最大化利用;
線(xiàn)程阻塞情況最小化。
JVM 常用參數詳解:
-server:一定要作為第一個(gè)參數,在多個(gè) CPU 時(shí)性能佳,還有一種叫 -client 的模式,特點(diǎn)是啟動(dòng)速度比較快,但運行時(shí)性能和內存管理效率不高,通常用于客戶(hù)端應用程序或開(kāi)發(fā)調試,在 32 位環(huán)境下直接運行 Java 程序默認啟用該模式。Server 模式的特點(diǎn)是啟動(dòng)速度比較慢,但運行時(shí)性能和內存管理效率很高,適用于生產(chǎn)環(huán)境,在具有 64 位能力的 JDK 環(huán)境下默認啟用該模式,可以不配置該參數。
-Xms:表示 Java 初始化堆的大小,-Xms 與-Xmx 設成一樣的值,避免 JVM 反復重新申請內存,導致性能大起大落,默認值為物理內存的 1/64,默認(MinHeapFreeRatio參數可以調整)空余堆內存小于 40% 時(shí),JVM 就會(huì )增大堆直到 -Xmx 的最大限制。
-Xmx:表示最大 Java 堆大小,當應用程序需要的內存超出堆的最大值時(shí)虛擬機就會(huì )提示內存溢出,并且導致應用服務(wù)崩潰,因此一般建議堆的最大值設置為可用內存的最大值的80%。如何知道我的 JVM 能夠使用最大值,使用 java -Xmx512M -version 命令來(lái)進(jìn)行測試,然后逐漸的增大 512 的值,如果執行正常就表示指定的內存大小可用,否則會(huì )打印錯誤信息,默認值為物理內存的 1/4,默認(MinHeapFreeRatio參數可以調整)空余堆內存大于 70% 時(shí),JVM 會(huì )減少堆直到-Xms 的最小限制。
-Xss:表示每個(gè) Java 線(xiàn)程堆棧大小,JDK 5.0 以后每個(gè)線(xiàn)程堆棧大小為 1M,以前每個(gè)線(xiàn)程堆棧大小為 256K。根據應用的線(xiàn)程所需內存大小進(jìn)行調整,在相同物理內存下,減小這個(gè)值能生成更多的線(xiàn)程,但是操作系統對一個(gè)進(jìn)程內的線(xiàn)程數還是有限制的,不能無(wú)限生成,經(jīng)驗值在 3000~5000 左右。一般小的應用, 如果棧不是很深, 應該是128k 夠用的,大的應用建議使用 256k 或 512K,一般不易設置超過(guò) 1M,要不然容易出現out ofmemory。這個(gè)選項對性能影響比較大,需要嚴格的測試。
-XX:NewSize:設置新生代內存大小。
-XX:MaxNewSize:設置最大新生代新生代內存大小
-XX:PermSize:設置持久代內存大小
-XX:MaxPermSize:設置最大值持久代內存大小,永久代不屬于堆內存,堆內存只包含新生代和老年代。
-XX:+AggressiveOpts:作用如其名(aggressive),啟用這個(gè)參數,則每當 JDK 版本升級時(shí),你的 JVM 都會(huì )使用最新加入的優(yōu)化技術(shù)(如果有的話(huà))。
-XX:+UseBiasedLocking:?jiǎn)⒂靡粋€(gè)優(yōu)化了的線(xiàn)程鎖,我們知道在我們的appserver,每個(gè)http請求就是一個(gè)線(xiàn)程,有的請求短有的請求長(cháng),就會(huì )有請求排隊的現象,甚至還會(huì )出現線(xiàn)程阻塞,這個(gè)優(yōu)化了的線(xiàn)程鎖使得你的appserver內對線(xiàn)程處理自動(dòng)進(jìn)行最優(yōu)調配。
-XX:+DisableExplicitGC:在 程序代碼中不允許有顯示的調用“System.gc()”。每次在到操作結束時(shí)手動(dòng)調用 System.gc() 一下,付出的代價(jià)就是系統響應時(shí)間嚴重降低,就和關(guān)于 Xms,Xmx 里的解釋的原理一樣,這樣去調用 GC 導致系統的 JVM 大起大落。
-XX:+UseConcMarkSweepGC:設置年老代為并發(fā)收集,即 CMS gc,這一特性只有 jdk1.5
后續版本才具有的功能,它使用的是 gc 估算觸發(fā)和 heap 占用觸發(fā)。我們知道頻頻繁的 GC 會(huì )造面 JVM
的大起大落從而影響到系統的效率,因此使用了 CMS GC 后可以在 GC 次數增多的情況下,每次 GC 的響應時(shí)間卻很短,比如說(shuō)使用了 CMS
GC 后經(jīng)過(guò) jprofiler 的觀(guān)察,GC 被觸發(fā)次數非常多,而每次 GC 耗時(shí)僅為幾毫秒。
-XX:+UseParNewGC:對新生代采用多線(xiàn)程并行回收,這樣收得快,注意最新的 JVM 版本,當使用 -XX:+UseConcMarkSweepGC 時(shí),-XX:UseParNewGC 會(huì )自動(dòng)開(kāi)啟。因此,如果年輕代的并行 GC 不想開(kāi)啟,可以通過(guò)設置 -XX:-UseParNewGC 來(lái)關(guān)掉。
-XX:MaxTenuringThreshold:設置垃圾最大年齡。如果設置為0的話(huà),則新生代對象不經(jīng)過(guò) Survivor 區,直接進(jìn)入老年代。對于老年代比較多的應用(需要大量常駐內存的應用),可以提高效率。如果將此值設置為一 個(gè)較大值,則新生代對象會(huì )在 Survivor 區進(jìn)行多次復制,這樣可以增加對象在新生代的存活時(shí)間,增加在新生代即被回收的概率,減少Full GC的頻率,這樣做可以在某種程度上提高服務(wù)穩定性。該參數只有在串行 GC 時(shí)才有效,這個(gè)值的設置是根據本地的 jprofiler 監控后得到的一個(gè)理想的值,不能一概而論原搬照抄。
-XX:+CMSParallelRemarkEnabled:在使用 UseParNewGC 的情況下,盡量減少 mark 的時(shí)間。
-XX:+UseCMSCompactAtFullCollection:在使用 concurrent gc 的情況下,防止 memoryfragmention,對 live object 進(jìn)行整理,使 memory 碎片減少。
-XX:LargePageSizeInBytes:指定 Java heap 的分頁(yè)頁(yè)面大小,內存頁(yè)的大小不可設置過(guò)大, 會(huì )影響 Perm 的大小。
-XX:+UseFastAccessorMethods:使用 get,set 方法轉成本地代碼,原始類(lèi)型的快速優(yōu)化。
-XX:+UseCMSInitiatingOccupancyOnly:只有在 oldgeneration 在使用了初始化的比例后 concurrent collector 啟動(dòng)收集。
-Duser.timezone=Asia/Shanghai:設置用戶(hù)所在時(shí)區。
-Djava.awt.headless=true:這個(gè)參數一般我們都是放在最后使用的,這全參數的作用是這樣的,有時(shí)我們會(huì )在我們的 J2EE 工程中使用一些圖表工具如:jfreechart,用于在 web 網(wǎng)頁(yè)輸出 GIF/JPG 等流,在 winodws 環(huán)境下,一般我們的 app server 在輸出圖形時(shí)不會(huì )碰到什么問(wèn)題,但是在linux/unix 環(huán)境下經(jīng)常會(huì )碰到一個(gè) exception 導致你在 winodws 開(kāi)發(fā)環(huán)境下圖片顯示的好好可是在 linux/unix 下卻顯示不出來(lái),因此加上這個(gè)參數以免避這樣的情況出現。
-Xmn:新生代的內存空間大小,注意:此處的大小是(eden+ 2 survivor space)。與 jmap -heap 中顯示的 New gen 是不同的。整個(gè)堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保證堆大小不變的情況下,增大新生代后,將會(huì )減小老生代大小。此值對系統性能影響較大,Sun官方推薦配置為整個(gè)堆的 3/8。
-XX:CMSInitiatingOccupancyFraction:當堆滿(mǎn)之后,并行收集器便開(kāi)始進(jìn)行垃圾收集,例如,當沒(méi)有足夠的空間來(lái)容納新分配或提升的對象。對于 CMS 收集器,長(cháng)時(shí)間等待是不可取的,因為在并發(fā)垃圾收集期間應用持續在運行(并且分配對象)。因此,為了在應用程序使用完內存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先啟動(dòng)。因為不同的應用會(huì )有不同對象分配模式,JVM 會(huì )收集實(shí)際的對象分配(和釋放)的運行時(shí)數據,并且分析這些數據,來(lái)決定什么時(shí)候啟動(dòng)一次 CMS 垃圾收集周期。這個(gè)參數設置有很大技巧,基本上滿(mǎn)足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100 >= Xmn 就不會(huì )出現 promotion failed。例如在應用中 Xmx 是6000,Xmn 是 512,那么 Xmx-Xmn 是 5488M,也就是老年代有 5488M,CMSInitiatingOccupancyFraction=90 說(shuō)明老年代到 90% 滿(mǎn)的時(shí)候開(kāi)始執行對老年代的并發(fā)垃圾回收(CMS),這時(shí)還 剩 10% 的空間是 5488*10% = 548M,所以即使 Xmn(也就是新生代共512M)里所有對象都搬到老年代里,548M 的空間也足夠了,所以只要滿(mǎn)足上面的公式,就不會(huì )出現垃圾回收時(shí)的 promotion failed,因此這個(gè)參數的設置必須與 Xmn 關(guān)聯(lián)在一起。
-XX:+CMSIncrementalMode:該標志將開(kāi)啟 CMS 收集器的增量模式。增量模式經(jīng)常暫停 CMS 過(guò)程,以便對應用程序線(xiàn)程作出完全的讓步。因此,收集器將花更長(cháng)的時(shí)間完成整個(gè)收集周期。因此,只有通過(guò)測試后發(fā)現正常 CMS 周期對應用程序線(xiàn)程干擾太大時(shí),才應該使用增量模式。由于現代服務(wù)器有足夠的處理器來(lái)適應并發(fā)的垃圾收集,所以這種情況發(fā)生得很少,用于但 CPU情況。
-XX:NewRatio:年輕代(包括 Eden 和兩個(gè) Survivor 區)與年老代的比值(除去持久代),-XX:NewRatio=4 表示年輕代與年老代所占比值為 1:4,年輕代占整個(gè)堆棧的 1/5,Xms=Xmx 并且設置了 Xmn 的情況下,該參數不需要進(jìn)行設置。
-XX:SurvivorRatio:Eden 區與 Survivor 區的大小比值,設置為 8,表示 2 個(gè) Survivor 區(JVM 堆內存年輕代中默認有 2 個(gè)大小相等的 Survivor 區)與 1 個(gè) Eden 區的比值為 2:8,即 1 個(gè) Survivor 區占整個(gè)年輕代大小的 1/10。
-XX:+UseSerialGC:設置串行收集器。
-XX:+UseParallelGC:設置為并行收集器。此配置僅對年輕代有效。即年輕代使用并行收集,而年老代仍使用串行收集。
-XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集,JDK6.0 開(kāi)始支持對年老代并行收集。
-XX:ConcGCThreads:早期 JVM 版本也叫-XX:ParallelCMSThreads,定義并發(fā) CMS 過(guò)程運行時(shí)的線(xiàn)程數。比如 value=4 意味著(zhù) CMS 周期的所有階段都以 4 個(gè)線(xiàn)程來(lái)執行。盡管更多的線(xiàn)程會(huì )加快并發(fā) CMS 過(guò)程,但其也會(huì )帶來(lái)額外的同步開(kāi)銷(xiāo)。因此,對于特定的應用程序,應該通過(guò)測試來(lái)判斷增加 CMS 線(xiàn)程數是否真的能夠帶來(lái)性能的提升。如果還標志未設置,JVM 會(huì )根據并行收集器中的 -XX:ParallelGCThreads 參數的值來(lái)計算出默認的并行 CMS 線(xiàn)程數。
-XX:ParallelGCThreads:配置并行收集器的線(xiàn)程數,即:同時(shí)有多少個(gè)線(xiàn)程一起進(jìn)行垃圾回收,此值建議配置與 CPU 數目相等。
-XX:OldSize:設置 JVM 啟動(dòng)分配的老年代內存大小,類(lèi)似于新生代內存的初始大小 -XX:NewSize。
以上就是一些常用的配置參數,有些參數是可以被替代的,配置思路需要考慮的是 Java 提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時(shí)間和頻度。收集垃圾能夠接受的速度和應用有關(guān),應該通過(guò)分析實(shí)際的垃圾收集的時(shí)間和頻率來(lái)調整。假如堆的大小很大,那么完全垃圾收集就會(huì )很慢,但是頻度會(huì )降低。假如您把堆的大小和內存的需要一致,完全收集就很快,但是會(huì )更加頻繁。調整堆大小的的目的是最小化垃圾收集的時(shí)間,以在特定的時(shí)間內最大化處理客戶(hù)的請求。在基準測試的時(shí)候,為確保最好的性能,要把堆的大小設大,確保垃圾收集不在整個(gè)基準測試的過(guò)程中出現。
假如系統花費很多的時(shí)間收集垃圾,請減小堆大小。一次完全的垃圾收集應該不超過(guò) 3-5 秒。假如垃圾收集成為瓶頸,那么需要指定代的大小,檢查垃圾收集的周詳輸出,研究垃圾收集參數對性能的影響。當增加處理器時(shí),記得增加內存,因為分配能夠并行進(jìn)行,而垃圾收集不是并行的。
3、設置系統屬性
之前說(shuō)過(guò),Tomcat 的語(yǔ)言編碼,配置起來(lái)很慢,要經(jīng)過(guò)多次設置才可以了,否則中文很有可能出現亂碼情況。譬如漢字“中”,以 UTF-8 編碼后得到的是 3 字節的值 %E4%B8%AD,然后通過(guò) GET 或者 POST 方式把這 3 個(gè)字節提交到 Tomcat 容器,如果你不告訴 Tomcat 我的參數是用 UTF-8編碼的,那么 Tomcat 就認為你是用 ISO-8859-1 來(lái)編碼的,而 ISO8859-1(兼容 URI 中的標準字符集 US-ASCII)是兼容 ASCII 的單字節編碼并且使用了單字節內的所有空間,因此 Tomcat 就以為你傳遞的用 ISO-8859-1 字符集編碼過(guò)的 3 個(gè)字符,然后它就用 ISO-8859-1 來(lái)解碼。
設置起來(lái)不難使用“ -D<名稱(chēng)>=<值> ”來(lái)設置系統屬性:
-Djavax.servlet.request.encoding=UTF-8
-Djavax.servlet.response.encoding=UTF-8
-Dfile.encoding=UTF-8
-Duser.country=CN
-Duser.language=zh
4、常見(jiàn)的 Java 內存溢出有以下三種
(1) java.lang.OutOfMemoryError: Java heap space —-JVM Heap(堆)溢出
JVM 在啟動(dòng)的時(shí)候會(huì )自動(dòng)設置 JVM Heap 的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)不可超過(guò)物理內存??梢岳?JVM提供的 -Xmn -Xms -Xmx 等選項可進(jìn)行設置。Heap 的大小是 Young Generation 和 Tenured Generaion 之和。在 JVM 中如果 98% 的時(shí)間是用于 GC,且可用的 Heap size 不足 2% 的時(shí)候將拋出此異常信息。
解決方法:手動(dòng)設置 JVM Heap(堆)的大小。
(2) java.lang.OutOfMemoryError: PermGen space —- PermGen space溢出。
PermGen space 的全稱(chēng)是 Permanent Generation space,是指內存的永久保存區域。為什么會(huì )內存溢出,這是由于這塊內存主要是被 JVM 存放Class 和 Meta 信息的,Class 在被 Load 的時(shí)候被放入 PermGen space 區域,它和存放 Instance 的 Heap 區域不同,sun 的 GC 不會(huì )在主程序運行期對 PermGen space 進(jìn)行清理,所以如果你的 APP 會(huì )載入很多 CLASS 的話(huà),就很可能出現 PermGen space 溢出。
解決方法: 手動(dòng)設置 MaxPermSize 大小
(3) java.lang.StackOverflowError —- 棧溢出
棧溢出了,JVM 依然是采用棧式的虛擬機,這個(gè)和 C 與 Pascal 都是一樣的。函數的調用過(guò)程都體現在堆棧和退棧上了。調用構造函數的 “層”太多了,以致于把棧區溢出了。通常來(lái)講,一般棧區遠遠小于堆區的,因為函數調用過(guò)程往往不會(huì )多于上千層,而即便每個(gè)函數調用需要 1K 的空間(這個(gè)大約相當于在一個(gè) C 函數內聲明了 256 個(gè) int 類(lèi)型的變量),那么棧區也不過(guò)是需要 1MB 的空間。通常棧的大小是 1-2MB 的。
通常遞歸也不要遞歸的層次過(guò)多,很容易溢出。
解決方法:修改程序。
更多信息,請參考以下文章:
JVM 垃圾回收調優(yōu)總結
http://developer.51cto.com/art/201201/312639.htmJVM調優(yōu)總結:典型配置舉例
http://developer.51cto.com/art/201201/311739.htmJVM基礎:JVM參數設置、分析
http://developer.51cto.com/art/201201/312018.htmJVM 堆內存相關(guān)的啟動(dòng)參數:年輕代、老年代和永久代的內存分配
http://www.2cto.com/kf/201409/334840.htmlJava 虛擬機–新生代與老年代GC
http://my.oschina.net/sunnywu/blog/332870JVM(Java虛擬機)優(yōu)化大全和案例實(shí)戰
http://blog.csdn.net/kthq/article/details/8618052JVM內存區域劃分Eden Space、Survivor Space、Tenured Gen,Perm Gen解釋
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836