tomcat服務二---tomcat調優
一、tomcat的基本原理
Tomcat伺服器的啟動是基於一個server.xml檔案的,Tomcat啟動的時候首先會啟動一個Server,Server裡面就會啟動Service,Service裡面就會啟動多個"Connector(聯結器)",每一個聯結器都在等待客戶機的連線,當有使用者使用瀏覽器去訪問伺服器上面的web資源時,首先是連線到Connector(聯結器),Connector(聯結器)是不處理使用者的請求的,而是將使用者的請求交給一個Engine(引擎)去處理,Engine(引擎)接收到請求後就會解析使用者想要訪問的Host,然後將請求交給相應的Host,Host收到請求後就會解析出使用者想要訪問這個Host下面的哪一個Web應用,一個web應用對應一個Context。
二、tomcat調優
1、記憶體調優,在canalina.sh中寫入如下內容
export JAVA_OPTS="-server -Xms4096m -Xmx4096m -XX:+PrintHeapAtGC -Xloggc:/usr/local/tomcat_front/logs/gc.log -XX:+PrintGCTimeStamps -XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:+PrintReferenceGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tomcat_front/logs/front1.bin"
引數解釋:
-server:執行jdk的server版本
-Xms:java虛擬機器初始化時堆的記憶體大小,一般配置Xmx配置為相同的值,這樣的好處是GC不必再為擴充套件記憶體空間而消耗效能
-Xmx:java虛擬機器可使用堆的最大記憶體
-XX:+PrintHeapAtGC
-Xloggc:/usr/local/tomcat_front/logs/gc.log
-XX:+PrintGCTimeStamps
-XX:+TraceClassLoading
-XX:+TraceClassUnloading
-XX:+PrintReferenceGC
-XX:+HeapDumpOnOutOfMemmoryError
-XX:HeapDumpPath=/usr/local/tomcat_front/logs/front1.bin
除了這些引數之外,還可以記錄其他引數,可參考jvm引數的配置。
設定成功後,可以使用jdk自帶的工具進行驗證,在JAVA_HOME/bin目錄下執行
$jps
$jump -heap 程序號
2、聯結器Connector調優,在server.xml中加入如下內容
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000" ##超時時間,毫秒,這裡是20秒
redirectPort="443"
maxThreads="3000" ##最大執行緒數
minSpareThreads="20" ##最小空閒執行緒數,這裡是一直會執行的執行緒
acceptCount="1000" ##接收的佇列數
enableLookups="false" ##關閉dns解析,減少效能損耗
server="None"
URIEncoding="UTF-8"
compression="on" ##開啟壓縮
compressionMinSize="2048" ##最小壓縮檔案的大小
noCompressionUserAgents="gozilla,traviata" ##這倆種瀏覽器下不壓縮
compressableMimeType="text/html,text/xml,text/javascript,application/x-javascript,application/javascript,text/css,text/plain" ##壓縮的格式
/>
3、執行緒池
Executor代表了一個執行緒池,可以在Tomcat元件之間共享。使用執行緒池的好處在於減少了建立銷燬執行緒的相關消耗,而且可以提高執行緒的使用效率。要想使用執行緒池,首先需要在 Service標籤中配置 Executor,如下:
<Service name="Catalina">
<Executor name="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="1000"
minSpareThreads="100"
maxIdleTime="60000"
maxQueueSize="Integer.MAX_VALUE"
prestartminSpareThreads="false"
threadPriority="5"
className="org.apache.catalina.core.StandardThreadExecutor"/>
....
其中,
name:執行緒池名稱,用於 Connector中指定。
namePrefix:所建立的每個執行緒的名稱字首,一個單獨的執行緒名稱為 namePrefix+threadNumber。
maxThreads:池中最大執行緒數。
minSpareThreads:活躍執行緒數,也就是核心池執行緒數,這些執行緒不會被銷燬,會一直存在。
maxIdleTime:執行緒空閒時間,超過該時間後,空閒執行緒會被銷燬,預設值為6000(1分鐘),單位毫秒。
maxQueueSize:在被執行前最大執行緒排隊數目,預設為Int的最大值,也就是廣義的無限。除非特殊情況,這個值不需要更改,否則會有請求不會被處理的情況發生。
prestartminSpareThreads:啟動執行緒池時是否啟動 minSpareThreads部分執行緒。預設值為false,即不啟動。
threadPriority:執行緒池中執行緒優先順序,預設值為5,值從1到10。
className:執行緒池實現類,未指定情況下,預設實現類為org.apache.catalina.core.StandardThreadExecutor。如果想使用自定義執行緒池首先需要實現org.apache.catalina.Executor介面。
程池配置完成後需要在 Connector中指定:
<Connector executor="tomcatThreadPool"
...
三、填坑心得(轉發)
http://www.cnblogs.com/hucn/p/3572384.html
我遇到這樣的問題,本地部署時丟擲異常java.lang.OutOfMemoryError:GC overhead limit exceeded導致服務起不來,檢視日誌發現載入了太多資源到記憶體,本地的效能也不好,gc時間消耗的較多。解決這種問題兩種方法是,增加引數,-XX:-UseGCOverheadLimit,關閉這個特性,同時增加heap大小,-Xmx1024m。坑填了,but why?
OOM大家都知道,就是JVM記憶體溢位了,那GC overhead limit exceed呢?
GC overhead limt exceed檢查是Hotspot VM 1.6定義的一個策略,通過統計GC時間來預測是否要OOM了,提前丟擲異常,防止OOM發生。Sun 官方對此的定義是:“並行/併發回收器在GC回收時間過長時會丟擲OutOfMemroyError。過長的定義是,超過98%的時間用來做GC並且回收了不到2%的堆記憶體。用來避免記憶體過小造成應用不能正常工作。“
聽起來沒啥用...預測OOM有啥用?起初開來這玩意只能用來Catch住釋放記憶體資源,避免應用掛掉。後來發現一般情況下這個策略不能拯救你的應用,但是可以在應用掛掉之前做最後的掙扎,比如資料儲存或者儲存現場(Heap Dump)。
而且有些時候這個策略還會帶來問題,比如載入某個大的記憶體資料時頻繁OOM。
假如你也生產環境中遇到了這個問題,在不知道原因時不要簡單的猜測和規避。可以通過-verbose:gc -XX:+PrintGCDetails看下到底什麼原因造成了異常。通常原因都是因為old區佔用過多導致頻繁Full GC,最終導致GC overhead limit exceed。如果gc log不夠可以藉助於JProfile等工具檢視記憶體的佔用,old區是否有記憶體洩露。分析記憶體洩露還有一個方法-XX:+HeapDumpOnOutOfMemoryError,這樣OOM時會自動做Heap Dump,可以拿MAT來排查了。還要留意young區,如果有過多短暫物件分配,可能也會拋這個異常。
日誌的資訊不難理解,就是每次gc時打條日誌,記錄GC的型別,前後大小和時間。舉個例子。
33.125: [GC [DefNew: 16000K->16000K(16192K), 0.0000574 secs][Tenured: 2973K->2704K(16384K), 0.1012650 secs] 18973K->2704K(32576K), 0.1015066 secs]
100.667:[Full GC [Tenured: 0K->210K(10240K), 0.0149142 secs] 4603K->210K(19456K), [Perm : 2999K->2999K(21248K)], 0.0150007 secs]
GC和Full GC代表gc的停頓型別,Full GC代表stop-the-world。箭頭兩邊是gc前後的區空間大小,分別是young區、tenured區和perm區,括號裡是該區的總大小。冒號前面是gc發生的時間,單位是秒,從jvm啟動開始計算。DefNew代表Serial收集器,為Default New Generation的縮寫,類似的還有PSYoungGen,代表Parallel Scavenge收集器。這樣可以通過分析日誌找到導致GC overhead limit exceeded的原因,通過調節相應的引數解決問題。
文中涉及到的名詞解釋,
Eden Space:堆記憶體池,大多數物件在這裡分配記憶體空間。
Survivor Space:堆記憶體池,儲存在Eden Space的gc中存活下來的物件。
Tenured Generation:堆記憶體池,儲存Survivor Space中存活過幾次gc的物件。
Permanent Generation:非堆空間,儲存的是class和method物件。
Code Cache:非堆空間,JVM用來儲存編譯和儲存native code。