Tomcat服務器性能優化

一、概述

本文檔主要介紹了Tomcat的性能調優的原理和方法。可作為公司技術人員為客戶Tomcat系統調優的技術指南,也可以提供給客戶的技術人員作為他們性能調優的指導手冊。

二、調優分類

由于Tomcat的運行依賴于JVM,從虛擬機的角度我們把Tomcat的調整分為外部環境調優和自身調優兩類來描述。

1. 外部環境調優

調整Tomcat運行環境的操作系統參數和運行Tomcat的java虛擬機參數。

(a) JAVA虛擬機性能優化

Tomcat需要依賴Java虛擬機運行。根據客戶選用的主機的操作系統選擇對應的 JDK的版本。無論哪個廠商的JDK,都建議使用最新的版本。 虛擬機可通過命令行的方式改變虛擬機使用內存的大小。如下表所示有兩個參數用來設置虛擬機使用內存的大小。

-Xms<size> :JVM初始化堆的大小

-Xmx<size> :JVM堆的最大值

Tomcat默認可以使用的內存較小,在較大型的應用項目中,這點內存是不夠的,需要調大。

Windows下,在文件tomcat_home/bin/catalina.bat,Unix下,在文件tomcat_home/bin/catalina.sh的前面,增加如下設置:

JAVA_OPTS=‘-Xms【初始化內存大小】 -Xmx【可以使用的最大內存】

需要把這個兩個參數值調大。例如:JAVA_OPTS='-Xms256m -Xmx512m' ,表示初始化內存為256MB,可以使用的最大內存為512MB。

另外需要考慮的是Java提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應用有關,應該通過分析實際的垃圾收集的時間和頻率來調整。

如果堆的空間很大,那么完全垃圾收集(FULL GC)就會很慢,但是頻度會降低。如果在客戶系統中把堆的大小和內存的需要一致,完全收集就很快,但是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。對于SUN和HP等虛擬機,推薦將最小堆大小和最大堆大小設置為同一值,因為這樣可以避免浪費用于時常調整堆大小所需的 VM 資源。

當然,客戶系統如果用到IBM虛擬機,要特別的注意設置-Xms和-Xmx一樣大小會耽誤垃圾回收的開始直到堆滿,這樣第一次垃圾回收就會變成非常昂貴的操作。推薦把-Xms設置為應用所需的最小值,這樣會產生高效的垃圾回收。

(b) 操作系統性能優化

以客戶系統為HP-UX為例。

HP系統中對Tomcat有影響的參數:

max_thread_proc: 一個進程所能創建的線程的最大數

nkthread: 在系統上同時允許的核心線程的最大數

如果在輸出里看到消息:java.lang.OutOfMemoryError: unable to create new native thread,則說明名為 max_thread_proc 的 Unix 內核設置過小。max_thread_proc 是單個進程中的最大線程數。 它必須大到能夠容納 Java 應用程序中的所有線程以及虛擬機本身中的部分額外線程。

查看核心參數:$ulimit -a

顯示輸出中的 nofiles 是指用戶的進程能同時打開的最大文件句柄數。如果日志中出現”two many open files”的異常,需要重點檢查這個參數。coredump 參數是 core 文件最大值的,限制當進程 coredump 時將產生 core文件的大小不能超過這個最大值。如果在日志文件檢查時,發現 core文件不完整,需要增大這個參數值。執行 ulimit -n 命令可以設置 nofiles 參數,執行ulimit -c命令設置 core 文件最大值。

如果是在Windows操作系統上使用Tomcat,那么最好選擇服務器版本。因為在非服務器版本上,最終用戶授權數或者操作系統本身所能承受的用戶數、可用的網絡連接數或其它方面的一些方面都是有限制的。并且基于安全性的考慮,必須經常給操作系統打上最新的補丁。

(c) Tomcat與其它Web服務器整合使用

雖然tomcat也可以作web服務器,但其處理靜態html的速度比不上apache,且其作為web服務器的功能遠不如apache,因此我們想把 apache和tomcat集成起來,將html與jsp的功能部分進行明確分工,讓tomcat只處理jsp部分,其它的由apache,IIS等這些 web服務器處理,由此大大節省了tomcat有限的工作線程。

2. 自身調優

本節將說明Tomcat性能調優的技巧和方法,這些技巧和方法與操作系統或Java虛擬機的種類無關。以下方法都是針對Tomcat 性能自身調整的最佳方式。

(a) 禁用DNS查詢

當web應用程序要記錄客戶端的信息時,它也會記錄客戶端的IP地址或者通過域名服務器查找機器名轉換為IP地址。DNS查詢需要占用網絡,并且包括可能從很多很遠的服務器或者不起作用的服務器上去獲取對應的IP的過程,這樣會消耗一定的時間。為了消除DNS查詢對性能的影響我們可以關閉DNS查詢,方式是修改server.xml 文件中的enableLookups參數值:

Tomcat4

<Connector className=“org.apache.coyote.tomcat4.CoyoteConnector”port=“80” minProcessors=“5” maxProcessors=“75” enableLookups=“false” redirectPort=“8443” acceptCount=“100” debug=“0” connectionTimeout=“20000” useURIValidationHack=“false” disableUploadTimeout=“true” />

Tomcat5

<Connector port=“80” maxThreads=“150” minSpareThreads=“25” maxSpareThreads=“75” enableLookups=“false” redirectPort=“8443” acceptCount=“100” debug=“0” connectionTimeout=“20000” disableUploadTimeout=“true”/>

除非客戶需要連接到站點的每個HTTP客戶端的機器名,否則我們建議在生產環境上關閉DNS查詢功能。可以通過Tomcat以外的方式來獲取機器名。這樣不僅節省了網絡帶寬、查詢時間和內存,而且更小的流量會使日志數據也會變得更少,顯而易見也節省了硬盤空間。對流量較小的站點來說禁用DNS查詢可能沒有大流量站點的效果明顯。

(b) 調整線程數

另外一個可通過應用程序的連接器(Connector)進行性能控制的參數是創建的處理請求的線程數。Tomcat使用線程池加速響應速度來處理請求。在Java中線程是程序運行時的路徑,是在一個程序中與其它控制線程無關的、能夠獨立運行的代碼段。它們共享相同的地址空間。多線程幫助程序員寫出CPU最大利用率的高效程序,使空閑時間保持最低,從而接受更多的請求。

Tomcat4中可以通過修改minProcessors和maxProcessors的值來控制線程數。這些值在安裝后就已經設定為默認值并且是足夠使用的,但是隨著站點的擴容而改大這些值。minProcessors服務器啟動時創建的處理請求的線程數應該足夠處理一個小量的負載。也就是說,如果一天內每秒僅發生5次單擊事件,并且每個請求任務處理需要1秒鐘,那么預先設置線程數為5就足夠了。但在你的站點訪問量較大時就需要設置更大的線程數,指定為參數maxProcessors的值。maxProcessors的值也是有上限的,應防止流量不可控制(或者惡意的服務攻擊),從而導致超出了虛擬機使用內存的大小。如果要加大并發連接數,應同時加大這兩個參數。web server允許的最大連接數還受制于操作系統的內核參數設置,通常Windows是2000個左右,Linux是1000個左右。

在Tomcat5對這些參數進行了調整:

maxThreads :Tomcat使用線程來處理接收的每個請求。這個值表示Tomcat可創建的最大的線程數。

acceptCount :指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理。

connnectionTimeout :網絡連接超時,單位:毫秒。設置為0表示永不超時,這樣設置有隱患的。通常可設置為30000毫秒。

minSpareThreads :Tomcat初始化時創建的線程數。

maxSpareThreads :一旦創建的線程超過這個值,Tomcat就會關閉不再需要的socket線程。

最好的方式是多設置幾次并且進行測試,觀察響應時間和內存使用情況。在不同的機器、操作系統或虛擬機組合的情況下可能會不同,而且并不是所有的web站點的流量都是一樣的,因此沒有一刀切的方案來確定線程數的值。

(c) 加速JSP編譯速度

當第一次訪問一個JSP文件時,它會被轉換為Java servlet源碼,接著被編譯成Java字節碼。客戶工程師可以控制使用哪個編譯器,默認情況下,Tomcat使用命令行javac進行使用的編譯器。也可以使用更快的編譯器,這里將介紹如何優化它們。

另外一種方法是不要把所有的實現都使用JSP頁面,而是使用一些不同的java模板引擎變量。

在Tomcat 4.0中可以使用流行而且免費的Jikes編譯器。Jikes編譯器的速度要高于Sun的Java編譯器。首先要安裝Jikes(可訪問http://oss.software.ibm.com/pub/jikes獲得更多的信息),接著需要在環境變量中設置JIKESPATH包含系統運行時所需的JAR文件。裝好Jikes以后還需要設置讓JSP編譯servlet使用Jikes,需要修改web.xml文件中jspCompilerPlugin的值:

<servlet>

<servlet-name>jsp</servlet-name>

<servlet-class>

org.apache.jasper.servlet.JspServlet

</servlet-class>

<init-param>

<param-name>logVerbosityLevel</param-name>

<param-value>WARNING</param-value>

</init-param>

<init-param>

<param-name>jspCompilerPlugin</param-name>

<param-value>org.apache.jasper.compiler.JikesJavaCompiler</param-value>

</init-param>

<init-param>

<!-- <param-name>org.apache.catalina.jsp_classpath</param-name> -->

<param-name>classpath</param-name>

<param-value>

/usr/local/jdk1.3.1-linux/jre/lib/rt.jar:

/usr/local/lib/java/servletapi/servlet.jar

</param-value>

</init-param>

<load-on-startup>3</load-on-startup>

</servlet>

在Tomcat 4.1(或更高版本),JSP的編譯由包含在Tomcat里面的Ant程序控制器直接執行。客戶開發人員需要在元素中定義一個名字叫”compiler”,并且在value中有一個支持編譯的編譯器名字,示例如下:

<servlet>

<servlet-name>jsp</servlet-name>

<servlet-class>

org.apache.jasper.servlet.JspServlet

</servlet-class>

<init-param>

<param-name>logVerbosityLevel</param-name>

<param-value>WARNING</param-value>

</init-param>

<init-param>

<param-name>compiler</param-name>

<param-value>jikes</param-value>

</init-param>

<load-on-startup>3</load-on-startup>

</servlet>

由于JSP頁面在第一次使用時已經被編譯,那么你可能希望在更新新的jsp頁面后馬上對它進行編譯。實際上,這個過程完全可以自動化,因為可以確認的是新的JSP頁面在生產服務器和在測試服務器上的運行效果是一樣的。

在Tomcat4的bin目錄下有一個名為jspc的腳本。它僅僅是運行翻譯階段,而不是編譯階段,使用它可以在當前目錄生成Java源文件。它是調試JSP頁面的一種有力的手段。

可以通過瀏覽器訪問再確認一下編譯的結果。這樣就確保了文件被轉換成servlet,被編譯了可直接執行。這樣也準確地模仿了真實用戶訪問JSP頁面,可以看到給用戶提供的功能。也抓緊這最后一刻修改出現的bug并且修改它。

Tomcat提供了一種通過請求來編譯JSP頁面的功能。客戶可以在瀏覽器地址欄中輸入http://localhost: 8080/examples/jsp/dates/date.jsp?jsp_precompile=true,這樣Tomcat就會編譯 data.jsp而不是執行它。此舉唾手可得,不失為一種檢驗頁面正確性的捷徑。

(d) NIO 配置

NIO (No-blocking I/O)從JDK 1.4起,NIO API作為一個基于緩沖區,并能提供非阻塞I/O操作的API被引入 。

TOMCAT可以支持高并發的企業級應用。其中有個很大的原因就是,配置良好的tomcat都會使用APR(Apache Portable Runtime),APR是Apache HTTP Server2.x的核心,它是高度可移植的本地庫,它使用高性能的UXIN I/O操作,低性能的java io操作,但是APR對客戶開發人員而言可能稍稍有點難度,在很多OS平臺上,可能需要重新編譯APR。但是從Tomcat6.0以后, 客戶開發人員很容易就可以用NIO的技術來提升tomcat的并發處理能力。但是為什么NIO可以提升tomcat的并發處理能力呢,我們先來看一下java 傳統io與 java NIO的差別。

Java 傳統的IO操作都是阻塞式的(blocking I/O), 如果有socket的編程基礎,你會接觸過堵塞socket和非堵塞socket,堵塞socket就是在accept、read、write等IO操作的時候,如果沒有可用符合條件的資源,不馬上返回,一直等待直到有資源為止。而非堵塞socket則是在執行select的時候,當沒有資源的時候堵塞,當有符合資源的時候,返回一個信號,然后程序就可以執行accept、read、write等操作,一般來說,如果使用堵塞socket,通常我們通常開一個線程accept socket,當讀完這次socket請求的時候,開一個單獨的線程處理這個socket請求;如果使用非堵塞socket,通常是只有一個線程,一開始是select狀,當有信號的時候可以通過多路復用(Multiplexing)技術傳遞給一個指定的線程池來處理請求,然后原來的線程繼續select狀態。 最簡單的多路復用技術可以通過java管道(Pipe)來實現。換句話說,如果客戶端的并發請求很大的時候,客戶系統可以使用少于客戶端并發請求的線程數來處理這些請求,而這些來不及立即處理的請求會被阻塞在java管道或者隊列里面,等待線程池的處理。

在web服務器上阻塞IO(BIO)與NIO一個比較重要的不同是,客戶系統使用BIO的時候往往會為每一個web請求引入多線程,每個web請求一個單獨的線程,所以并發量一旦上去了,線程數就上去了,CPU就忙著線程切換,所以BIO不合適高吞吐量、高可伸縮的web服務器;而NIO則是使用單線程(單個CPU)或者只使用少量的多線程(多CPU)來接受Socket,而由線程池來處理堵塞在pipe或者隊列里的請求.這樣的話,只要OS可以接受TCP的連接,web服務器就可以處理該請求。大大提高了web服務器的可伸縮性。

客戶只需要在server.xml里把 HTTP Connector做如下更改,

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
改為
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443" />

然后啟動服務器,如果出現org.apache.coyote.http11.Http11NioProtocol start的提示信息,表示NIO已經啟動。其他的配置請參考官方配置文檔。

(e) 其他

前面我們提到過操作系統通過一些限制手段來防止惡意的服務攻擊,同樣Tomcat也提供了防止惡意攻擊或禁止某些機器訪問的設置。

Tomcat提供了兩個參數供你配置:RemoteHostValve 和RemoteAddrValve。 通過配置這兩個參數,可以讓你過濾來自請求的主機或IP地址,并允許或拒絕哪些主機/IP。與之類似的,在Apache的httpd文件里有對每個目錄的允許/拒絕指定。

例如你可以把Admin Web application設置成只允許本地訪問,設置如下:

<Context path=“/path/to/secret_files” >

<Valve className=“org.apache.catalina.valves.RemoteAddrValve”

allow=“127.0.0.1”deny=““/>

</Context>

如果沒有給出允許主機的指定,那么與拒絕主機匹配的主機就會被拒絕,除此之外的都是允許的。與之類似,如果沒有給出拒絕主機的指定,那么與允許主機匹配的主機就會被允許,除此之外的都是拒絕的。


本文轉自:點擊打開鏈接

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443728.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443728.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443728.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分布式系統概念 | 分布式事務:2PC、3PC、本地消息表

文章目錄分布式事務2PC&#xff08;二階段提交協議&#xff09;執行流程優缺點3PC&#xff08;三階段提交協議&#xff09;執行流程優缺點本地消息表&#xff08;異步確保&#xff09;分布式事務 分布式事務就是指事務的參與者、支持事務的服務器、資源服務器以及事務管理器分…

數據結構算法 | 單調棧

文章目錄算法概述題目下一個更大的元素 I思路代碼下一個更大元素 II思路代碼132 模式思路代碼接雨水思路算法概述 當題目出現 「找到最近一個比其大的元素」 的字眼時&#xff0c;自然會想到 「單調棧」 。——三葉姐 單調棧以嚴格遞增or遞減的規則將無序的數列進行選擇性排序…

最長下降子序列

文章目錄題目解法DP暴搜思路代碼實現貪心二分思路代碼實現題目 給出一組數據 nums&#xff0c;求出其最長下降子序列&#xff08;子序列允許不連續&#xff09;的長度。&#xff08;類似于lc的最長遞增子序列&#xff09; 示例&#xff1a; 輸入&#xff1a; 6 // 數組元素個…

Linux 服務器程序規范、服務器日志、用戶、進程間的關系

文章目錄服務器程序規范日志rsyslogd 守護進程syslog函數openlog函數setlogmask函數closelog函數用戶進程間的關系進程組會話系統資源限制改變工作目錄和根目錄服務器程序后臺化服務器程序規范 Linux 服務器程序一般以后臺進程&#xff08;守護進程[daemon]&#xff09;形式運…

IO模型 :阻塞IO、非阻塞IO、信號驅動IO、異步IO、多路復用IO

文章目錄IO模型阻塞IO非阻塞IO信號驅動IO多路復用IO異步IOIO模型 根據各自的特性不同&#xff0c;IO模型被分為阻塞IO、非阻塞IO、信號驅動IO、異步IO、多路復用IO五類。 最主要的兩個區別就是阻塞與非阻塞&#xff0c;同步與異步。 阻塞與非阻塞 阻塞與非阻塞最主要的區別就…

Tomcat服務器集群與負載均衡實現

一、前言 在單一的服務器上執行WEB應用程序有一些重大的問題&#xff0c;當網站成功建成并開始接受大量請求時&#xff0c;單一服務器終究無法滿足需要處理的負荷量&#xff0c;所以就有點顯得有點力不從心了。另外一個常見的問題是會產生單點故障&#xff0c;如果該服務器壞掉…

Linux服務器 | 事件處理模式:Reactor模式、Proactor模式

文章目錄Reactor模式Proactor模式同步I/O模型模擬Proactor模式兩者的優缺點ReactorProactor同步I/O模型通常用于實現 Reactor 模式&#xff0c;異步I/O模型通常用于實現 Proactor 模式。&#xff08;不是絕對的&#xff0c;同步I/O也可模擬出 Proactor 模式&#xff09; React…

Linux服務器 | 服務器模型與三個模塊、兩種并發模式:半同步/半異步、領導者/追隨者

文章目錄兩種服務器模型及三個模塊C/S模型P2P模型I/O處理單元、邏輯單元、存儲單元并發同步與異步半同步/半異步模式變體&#xff1a;半同步/半反應堆模式改進&#xff1a;高效的半同步/半異步模式領導者/追隨者模式組件 &#xff1a;句柄集、線程集、事件處理器工作流程兩種服…

香農信息熵之可憐的小豬

文章目錄題目解析香農熵公式樣例具體分析代碼題目 有 n 桶液體&#xff0c;其其中 正好 有一桶含有毒藥&#xff0c;其裝的都是水。它們從外觀看起來都一樣。為了弄清楚哪只水桶含有毒藥&#xff0c;你可以喂一些豬喝&#xff0c;通過觀察豬是否會死進行判斷&#xff0c;實驗對…

字符串匹配之KMP(KnuthMorrisPratt)算法(圖解)

文章目錄最長相等前后綴next數組概念代碼實現圖解GetNext中的回溯改進代碼實現代碼復雜度分析最長相等前后綴 給出一個字符串 ababa 前綴集合&#xff1a;{a, ab, aba, abab} 后綴集合&#xff1a;{a, ba, aba, baba} 相等前后綴 即上面用同樣顏色標識出來的集合元素&#…

linux下tomcat6.0與jdk安裝詳細步驟

安裝Tomcat6.0和JDK1.6 在linux系統上安裝tomcat和jdk應該說是我學習linux知識的第一課了&#xff0c;之前只 是聽說過&#xff0c;從沒接觸過&#xff0c;但我們公司項目都是部署在linux系統上的&#xff0c;那天上司突 然給我發了幾個文檔&#xff0c;讓我看一下&#xff…

Android入門(一) | Android Studio的配置與使用

文章目錄安裝配置Android Studio使用Android Studio模擬器更改Android SDK的路徑Hello World&#xff01;安裝配置Android Studio 從這一步開始&#xff1a; 一直點 next 即可&#xff0c;直到存儲路徑的選擇上&#xff0c;可以放到非 C 盤&#xff0c;這里我放到 D 盤了&am…

Android 入門(四) | Intent 實現 Activity 切換

文章目錄Intent顯式 Intent定義兩個 xml 文件android:orientationmatch_parent 和 wrap_contentIntent函數定義兩個 Activity隱式 Intent更多隱式 Intent 的用法用隱式 Intent 打開系統瀏覽器自建 Activity 以響應打開網頁的 Intent向下一個活動傳遞數據返回數據給上一個活動In…

Android入門(二) | 項目目錄及主要文件作用分析

文章目錄項目目錄分析app目錄分析AndroidManifest.xml 分析MainActivity.kt 分析build.gradle 分析最外層目錄下的 build.gradleapp 目錄下的 build.gradle項目目錄分析 我們來看一下 src/main/res 下的一些文件&#xff1a; .gradle 和 .idea &#xff1a;這兩個目錄下放置…

Android入門(三) | Android 的日志工具 Logcat

文章目錄日志工具類 android.util.LogLogcat 中的過濾器日志工具類 android.util.Log Log 從屬日志工具類 android.util.Log &#xff0c;該類提供了五個方法供我們打印日志&#xff1a; Log.v() &#xff1a;用于打印那些最為瑣碎的、意義最小的日志信息。對應級別 verbose&…

Android 客戶端與服務器交互方式

突然想到一個問題就是Android客戶端與服務器交互有幾種方式&#xff0c;因為在腦袋里想當然的就是webservices和json。要在Android手機客戶端與pc服務器交互&#xff0c;需要滿足下面幾種條件&#xff1a;跨平臺、傳輸數據格式標準、交互方便...。 為了與服務器通訊其實無非就…

Android入門(五) | Activity 的生命周期

文章目錄Activity 的狀態及生命周期實現管理生命周期FirstActivitySecondActivityDialogActivity運行結果舊活動被回收了還能返回嗎&#xff1f;Activity 的狀態及生命周期 Android 的應用程序運用 棧&#xff08;Back Stack&#xff09; 的思想來管理 Activity&#xff1a; …

Android入門(六) | Activity 的啟動模式 及 生產環境中關于 Activity 的小技巧

文章目錄Activity 的啟動模式standardsingleTopsingleTasksingleInstance技巧了解當前界面是哪個 Activity隨時隨地退出程序啟動活動的最佳寫法Activity 的啟動模式 standard&#xff1a;默認的啟動方式&#xff0c;每次啟動一個活動都會重新創建singleTop&#xff1a;如果該活…

Android入門(七) | 常用控件

文章目錄TextView 控件&#xff1a;文本信息Button 控件&#xff1a;按鈕EditText 控件&#xff1a;輸入框ImageView 控件&#xff1a;圖片ProgressBar 控件&#xff1a;進度條AlertDialog 控件&#xff1a;提示框ProgressDialog 控件&#xff1a;帶有進度條的提示框TextView 控…

Android入門(八) | 常用的界面布局 及 自定義控件

文章目錄LinearLayout &#xff1a;線性布局android:layout_gravity &#xff1a;控件的對齊方式android:layout_weight&#xff1a;權重RelativeLayout &#xff1a;相對布局相對于父布局進行定位相對于控件進行定位邊緣對齊FrameLayout &#xff1a;幀布局Percent &#xff1…