Tomcat部署及優化
一、Tomcat安裝部署
一、安裝jdk和Tomcat
1、上傳jdk和Tomcat
mkdir -p /opt/tools/ /application ##jdk:jdk-8u131 tomcat:9.0 cd /opt/tools/ rz apache-tomcat-9.0.0.M17.tar.gz jdk-8u131-linux-x64.tar.gz
2、解壓jdk和Tomcat
1、jdk部署 tar xf jdk-8u131-linux-x64.tar.gz -C /application chown -R root.root /application/jdk1.8.0_131/ ln -s /application/jdk1.8.0_131/ /application/jdk 2、Tomcat部署 tar xf apache-tomcat-9.0.0.M17.tar.gz -C /application chown -R root.root /application/apache-tomcat-9.0.0.M17/ ln -s /application/apache-tomcat-9.0.0.M17/ /application/tomcat
3、設定環境變量
方法一:vim設置/etc/profile
#jdk export JAVA_HOME=/application/jdk export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH #tomcat export TOMCAT_HOME=/application/tomcat export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
方法二:sed追加
sed -i.bak ‘$a export JAVA_HOME=/application/jdk\nexport PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH\nexport CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar‘ /etc/profile
使配置生效,查看java版本
source /etc/profile
java -version
二、Tomcat配置文件server.xml詳解
<Server port="8015" shutdown="WZSSHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> <!-- Define an AJP 1.3 Connector on port 8009 --> <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --> <Connector port="8221" protocol="HTTP/1.1" #port 端口配置 connectionTimeout="20000" #connectionTimeout指定超時的時間數(以毫秒為單位) maxThreads="3000" #tomcat起動的最大線程數,即同時處理的任務個數,默認值為200 minSpareThreads="100" #初始化時創建的線程數 acceptCount="800" #指定當所有可以使用的處理請求的線程數都被使用時, 可以放到處理隊列中的請求數,超過這個數的請求將不予處理 maxKeepAliveRequests="200" #表示該連接最大支持的請求數。超過該請求數的連接也將被關閉(此時就會返回一個Connection: close頭給客戶端)。 URIEncoding="UTF-8" #指定字符集 redirectPort="8443" /> #指定服務器正在處理http請求時收到了一個SSL傳輸請求後重定向的端口號/application/tomcat/conf/server.xml
三、Tomcat的日誌級別
1、日誌級別詳解
#可配置項(5類日誌):catalina、localhost、manager、admin、host-manager handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler #日誌輸出為輸出到文件和輸出到控制臺 .handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler #日誌輸出級別:SEVERE (最高級別) > WARNING > INFO > CONFIG > FINE > FINER(精心) > FINEST (所有內容,最低級別) #配置文件使catalina日誌輸出級別為FINE 1catalina.org.apache.juli.FileHandler.level = FINE #catalina文件輸出位置 1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs #catalina日誌前綴為catalina 1catalina.org.apache.juli.FileHandler.prefix = catalina. #配置文件使localhost日誌輸出級別為FINE 2localhost.org.apache.juli.FileHandler.level = FINE #localhost文件輸出位置 2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs #localhost日誌前綴為localhost 2localhost.org.apache.juli.FileHandler.prefix = localhost. #配置文件使manager日誌輸出級別為FINE 3manager.org.apache.juli.FileHandler.level = FINE #manager文件輸出位置 3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs #manager日誌前綴為manager 3manager.org.apache.juli.FileHandler.prefix = manager. #配置文件使host-manager日誌輸出級別為FINE 4host-manager.org.apache.juli.FileHandler.level = FINE #host-manager文件輸出位置 4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs #host-manager日誌前綴為host-manager 4host-manager.org.apache.juli.FileHandler.prefix = host-manager. #配置文件使控制臺日誌輸出級別為FINE java.util.logging.ConsoleHandler.level = FINE #控制臺日誌輸出格式 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter #localhost日誌文件輸出級別為INFO org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO #localhost日誌文件輸出處理類2localhost.org.apache.juli.FileHandler org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler #manager日誌文件輸出級別為INFO org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO #manager日誌文件輸出處理類3manager.org.apache.juli.FileHandler org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler #host-manager日誌文件輸出級別為INFO org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO #host-manager日誌文件輸出處理類4host-manager.org.apache.juli.FileHandler org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler
2、修改Tomcat默認的日誌級別,減少日誌量
將logging.properties將FINE改成INFO
二、Tomcat優化
一、內存優化
默認情況下Tomcat的相關內存配置較低,這對於一些大型項目顯然是不夠用的,這些項目運行就已經耗費了大部分內存空間,何況大規模訪問的情況。
1、內存問題
即使是本文中的這個只有一個頁面的超小項目,在並發達到一定程度後也會拋出以下類似異常:
嚴重: Exception invoking periodic operation: java.lang.OutOfMemoryError: Java heap space
嚴重: Error processing request java.lang.OutOfMemoryError: GC overhead limit exceeded
說明Tomcat已經無力支持訪問處理,內部GC也已經“無能無力”。所以一般情況下我們需要重新配置Tomcat的相關內存大小。
2、修改內存等jvm相關配置
Linux下修改TOMCAT_HOME/bin/catalina.sh,在其中加入,可以放在CLASSPATH=下面(#OS specific添加以下代碼):
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=512m"
windows下修改TOMCAT_HOME/bin/catalina.bat,在其中加入,可以放在set CLASSPATH=下面:
set JAVA_OPTS=-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx
3、JVM參數詳解
- -Xms:初始堆內存Heap大小,使用的最小內存,cpu性能高時此值應設的大一些
- -Xmx:初始堆內存heap最大值,使用的最大內存
- 上面兩個值是分配JVM的最小和最大內存,取決於硬件物理內存的大小,建議均設為物理內存的一半。
- -XX:PermSize:設定內存的永久保存區域
- -XX:MaxPermSize:設定最大內存的永久保存區域
- -XX:MaxNewSize:
- -Xss 15120 這使得JBoss每增加一個線程(thread)就會立即消耗15M內存,而最佳值應該是128K,默認值好像是512k.
- +XX:AggressiveHeap 會使得 Xms沒有意義。這個參數讓jvm忽略Xmx參數,瘋狂地吃完一個G物理內存,再吃盡一個G的swap。
- -Xss:每個線程的Stack大小
- -verbose:gc 現實垃圾收集信息
- -Xloggc:gc.log 指定垃圾收集日誌文件
- -Xmn:young generation的heap大小,一般設置為Xmx的3、4分之一
- -XX:+UseParNewGC :縮短minor收集的時間
- -XX:+UseConcMarkSweepGC :縮短major收集的時間
4、驗證
1、JDK自帶的驗證工具
設置成功後我們可以利用JDK自帶的工具進行驗證,這些工具都在JAVA_HOME/bin目錄下:
1 jps:用來顯示本地的java進程,以及進程號,進程啟動的路徑等。 2 jmap:觀察運行中的JVM 物理內存的占用情況,包括Heap size , Perm size 下載地址 等。
2、jps工具
進入命令行模式後,進入JAVA_HOME/bin目錄下,然後輸入jps命令:其中Bootstrap進程是啟動Tomcat的進程。
# jps 9635 Jps 6601 -- process information unavailable 36884 Bootstrap
3、jmap工具
jmap查看其內存相關配置
# jmap -heap 36884 Attaching to process ID 36884, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.79-b02 using parallel threads in the new generation. using thread-local object allocation. Concurrent Mark-Sweep GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 4294967296 (4096.0MB) //最大堆內存 NewSize = 2147483648 (2048.0MB) MaxNewSize = 2147483648 (2048.0MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 4 PermSize = 268435456 (256.0MB) //永久代初始大小 MaxPermSize = 536870912 (512.0MB) ////永久代最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 1789591552 (1706.6875MB) used = 196280728 (187.1878890991211MB) free = 1593310824 (1519.499610900879MB) 10.96790649132434% used Eden Space: capacity = 1431699456 (1365.375MB) used = 180701304 (172.33019256591797MB) free = 1250998152 (1193.044807434082MB) 12.621455099582017% used From Space: capacity = 357892096 (341.3125MB) used = 15579424 (14.857696533203125MB) free = 342312672 (326.4548034667969MB) 4.353106473745651% used To Space: capacity = 357892096 (341.3125MB) used = 0 (0.0MB) free = 357892096 (341.3125MB) 0.0% used concurrent mark-sweep generation: capacity = 2147483648 (2048.0MB) used = 637442344 (607.9123916625977MB) free = 1510041304 (1440.0876083374023MB) 29.683222249150276% used Perm Generation: capacity = 268435456 (256.0MB) used = 116514152 (111.1165542602539MB) free = 151921304 (144.8834457397461MB) 43.40490400791168% used 74530 interned Strings occupying 7681632 bytes.
從結果可以看出配置已經成功了。
二、配置優化
TOMCAT_HOME/conf/server.xml可以配置端口,虛擬路徑等等 Tomcat相關主要配置。
1、Connector 優化
Connector是連接器,負責接收客戶的請求,以及向客戶端回送響應的消息。所以 Connector的優化是重要部分。默認情況下 Tomcat只支持200線程訪問,超過這個數量的連接將被等待甚至超時放棄,所以我們需要提高這方面的處理能力。
修改這部分配置需要修改TOMCAT_HOME/conf/server.xml,打開server.xml找到Connector 標簽項,默認配置如下:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
其中port代表服務接口;protocol代表協議類型;connectionTimeout代表連接超時時間,單位為毫秒;redirectPort代表安全通信(https)轉發端口,一般配置成443。
可以看到除了這幾個基本配置外並無特殊功能,所以我們需要對 Connector 進行擴展。
其中Connector 支持參數屬性可以參考Tomcat官方網站(https://tomcat.apache.org/tomcat-8.0-doc/config/http.html),非常多,所以本文就只介紹些常用的。
我們將 Connector 配置修改為如下:
<Connector port="8080" protocol="HTTP/1.1" maxThreads="1000" minSpareThreads="100" acceptCount="1000" maxConnections="1000" connectionTimeout="20000" maxHttpHeaderSize="8192" tcpNoDelay="true" compression="on" compressionMinSize="2048" disableUploadTimeout="true" redirectPort="8443" enableLookups="false" URIEncoding="UTF-8" />
1、port:
代表Tomcat監聽端口,也就是網站的訪問端口,默認為8080,可以根據需要改成其他。
2、protocol:
協議類型,可選類型有四種,分別為BIO(阻塞型IO),NIO,NIO2和APR。
(1)BIO:BIO(Blocking I/O),顧名思義,即阻塞式I/O操作,表示Tomcat使用的是傳統的Java I/O操作(即java.io包及其子包)。Tomcat在默認情況下,是以bio模式運行的。遺憾的是,就一般而言,bio模式是三種運行模式中性能最低的一種。BIO配置采用默認即可。
(2)NIO:NIO(New I/O),是Java SE 1.4及後續版本提供的一種新的I/O操作方式(即java.nio包及其子包)。Java nio是一個基於緩沖區、並能提供非阻塞I/O操作的Java API,因此nio也被看成是non-blocking I/O的縮寫。它擁有比傳統I/O操作(bio)更好的並發運行性能。要讓Tomcat以nio模式來運行也比較簡單,我們只需要protocol類型修改為:
//NIO protocol="org.apache.coyote.http11.Http11NioProtocol" //NIO2 protocol="org.apache.coyote.http11.Http11Nio2Protocol"
(3)APR:APR(Apache Portable Runtime/Apache可移植運行時),是Apache HTTP服務器的支持庫。你可以簡單地理解為:Tomcat將以JNI的形式調用 Apache HTTP服務器的核心動態鏈接庫來處理文件讀取或網絡傳輸操作,從而大大地提高 Tomcat對靜態文件的處理性能。
與配置 NIO運行模式一樣,也需要將對應的 Connector節點的 protocol屬性值改為:
protocol="org.apache.coyote.http11.Http11AprProtocol"
相關APR介紹及配置會在下面專門講。
3、maxThreads:
由該連接器創建的處理請求線程的最大數目,也就是可以處理的同時請求的最大數目。如果未配置默認值為200。如果一個執行器與此連接器關聯,則忽略此屬性,因為該屬性將被忽略,所以該連接器將使用執行器而不是一個內部線程池來執行任務。
maxThreads是一個重要的配置屬性,maxThreads配置的合理直接影響了Tomcat的相關性能,所以這裏我們重點討論下。
maxThreads並不是配置的越大越好,事實上你即使配置成999999也是沒有用的,因為這個最大值是受操作系統及相關硬件所制約的,並且最大值並不一定是最優值,所以我們追尋的應該是最優值而不是最大值。
QPS(Query Per Second):每秒查詢率QPS是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。我們常常使用 QPS值來衡量一個服務器的性能。
QPS = 並發數 / 平均響應時間
或者
並發數 = QPS * 平均響應時間
一個系統吞吐量通常由QPS、並發數兩個因素決定,每套系統的這兩個值都有一個相對極限值,在應用場景訪問壓力下,只要某一項達到系統最高值,系統的吞吐量就上不去了,如果壓力繼續增大,系統的吞吐量反而會下降,原因是系統超負荷工作,上下文切換、內存等等其它消耗導致系統性能下降。所謂吞吐量這裏可以理解為每秒能處理請求的次數。
所以選擇一個合理的 maxThreads值,其實並不是那麽容易的事。因為過多的線程只會造成,更多的內存開銷,更多的CPU開銷,但是對提升QPS確毫無幫助;找到最佳線程數後通過簡單的設置,可以讓web系統更加穩定,得到最高,最穩定的QPS輸出。
我們可以通過以下幾種方式來獲取 maxThreads的最佳值:
(1)通過線上系統不斷使用和用戶的不斷增長來進行性能測試,觀察QPS,響應時間,這種方式會在爆發式增長時系統崩潰,如雙12等。
(2)根據公式計算,服務器端最佳線程數量=((線程等待時間+線程cpu時間)/線程cpu時間) * cpu數量,這種方式有時會被誤導,因為某些系統處理環節可能會耗時比較長,從而影響公式的結果。
(3)單、多用戶壓力測試,查看CPU的消耗,然後直接乘以百分比,再進行壓測,一般這個值的附近應該就是最佳線程數量,這種方式理想場景比較適用,實際情況會比這個復雜的多。
(4)根據系統的自身情況調整,如硬件限制,系統限制,程序處理能力限制等。
(5)定期修改為不同的 maxThreads值,看服務器響應結果及用戶反應。
QPS和線程數的關系
(1)在最佳線程數量之前,QPS和線程是互相遞增的關系,線程數量到了最佳線程之後,QPS持平,不在上升,甚至略有下降,同時相應時間持續上升。
(2)同一個系統而言,支持的線程數越多(最佳線程數越多而不是配置的線程數越多),QPS越高。
QPS和響應時間的關系
(1)對於一般的web系統,響應時間一般有CPU執行時間+IO等待時間組成。
(2)CPU的執行時間減少,對QPS有實質的提升,IO時間的減少,對QPS提升不明顯。如果要想明顯提升QPS,優化系統的時候要著重優化CPU消耗大戶。
所以想要找出 maxThreads的最優值可並不容易,沒有最好只有更好,更好的值只能通過時間來顯現,如果你不想考慮那麽多,一般情況下設置成1000即可。
4、minSpareThreads:
線程的最小運行數目,這些始終保持運行。如果未指定,默認值為10。
5、acceptCount:
當所有可能的請求處理線程都在使用時傳入連接請求的最大隊列長度。如果未指定,默認值為100。一般是設置的跟 maxThreads一樣或一半,此值設置的過大會導致排隊的請求超時而未被處理。所以這個值應該是主要根據應用的訪問峰值與平均值來權衡配置。
6、maxConnections:
在任何給定的時間內,服務器將接受和處理的最大連接數。當這個數字已經達到時,服務器將接受但不處理,等待進一步連接。NIO與NIO2的默認值為10000,APR默認值為8192。
7、connectionTimeout:
當請求已經被接受,但未被處理,也就是等待中的超時時間。單位為毫秒,默認值為60000。通常情況下設置為30000。
8、maxHttpHeaderSize:
請求和響應的HTTP頭的最大大小,以字節為單位指定。如果沒有指定,這個屬性被設置為8192(8 KB)。
9、tcpNoDelay:
如果為true,服務器socket會設置TCP_NO_DELAY選項,在大多數情況下可以提高性能。缺省情況下設為true。
10、compression:
是否啟用gzip壓縮,默認為關閉狀態。這個參數的可接受值為“off”(不使用壓縮),“on”(壓縮文本數據),“force”(在所有的情況下強制壓縮)。
11、compressionMinSize:
如果compression="on",則啟用此項。被壓縮前數據的最小值,也就是超過這個值後才被壓縮。如果沒有指定,這個屬性默認為“2048”(2K),單位為byte。
12、disableUploadTimeout:
這個標誌允許servlet Container在一個servlet執行的時候,使用一個不同的,更長的連接超時。最終的結果是給servlet更長的時間以便完成其執行,或者在數據上載的時候更長的超時時間。如果沒有指定,設為false。
13、enableLookups:
關閉DNS反向查詢。
14、URIEncoding:
URL編碼字符集。
Connector 還有很多其他參數,可以參考Tomcat官網,這裏只介紹與性能相關的部分。
2、BIO、NIO、APR
通過配置 protocol的類型可以使用不同的 Connector處理請求。
//BIO protocol="HTTP/1.1" //NIO protocol="org.apache.coyote.http11.Http11NioProtocol" //NIO2 protocol="org.apache.coyote.http11.Http11Nio2Protocol" //APR protocol="org.apache.coyote.http11.Http11AprProtocol"
以下是幾種類型 Connector的參數對比:
並不是說 BIO的性能就一定不如 NIO,這幾種類型 Connector之間並沒有明顯的性能區別,它們之間實現流程和原理不同,所以它們的選擇是需要根據應用的類型來決定的。
BIO更適合處理簡單流程,如程序處理較快可以立即返回結果。簡單項目及應用可以采用BIO。
NIO更適合後臺需要耗時完成請求的操作,如程序接到了請求後需要比較耗時的處理這已請求,所以無法立即返回結果,這樣如果采用BIO就會占用一個連接,而使用NIO後就可以將此連接轉讓給其他請求,直至程序處理完成返回為止。
APR可以大大提升Tomcat對靜態文件的處理性能,同時如果你使用了HTTPS方式傳輸的話,也可以提升SSL的處理性能。
本文的最後會對幾種 Connector進行對比測試。
3、線程池
Executor代表了一個線程池,可以在Tomcat組件之間共享。使用線程池的好處在於減少了創建銷毀線程的相關消耗,而且可以提高線程的使用效率。
1、要想使用線程池,首先需要在 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"/> ....
2、參數詳解
1 name:線程池名稱,用於 Connector中指定。 2 namePrefix:所創建的每個線程的名稱前綴,一個單獨的線程名稱為 namePrefix+threadNumber。 3 maxThreads:池中最大線程數。 4 minSpareThreads:活躍線程數,也就是核心池線程數,這些線程不會被銷毀,會一直存在。 5 maxIdleTime:線程空閑時間,超過該時間後,空閑線程會被銷毀,默認值為6000(1分鐘),單位毫秒。 6 maxQueueSize:在被執行前最大線程排隊數目,默認為Int的最大值,也就是廣義的無限。除非特殊情況,這個值不需要更改,否則會有請求不會被處理的情況發生。 7 prestartminSpareThreads:啟動線程池時是否啟動 8 minSpareThreads部分線程。默認值為false,即不啟動。 9 threadPriority:線程池中線程優先級,默認值為5,值從1到10。 10 className:線程池實現類,未指定情況下,默認實現類為org.apache.catalina.core.StandardThreadExecutor。如果想使用自定義線程池首先需要實現 org.apache.catalina.Executor接口。
3、線程池配置完成後需要在 Connector中指定:
<Connector executor="tomcatThreadPool" ...
4、Listener
另一個影響Tomcat 性能的因素是內存泄露。Server標簽中可以配置多個Listener,其中 JreMemoryLeakPreventionListener是用來預防JRE內存泄漏。此Listener只需在Server標簽中配置即可,默認情況下無需配置,已經添加在 Server中。
Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
三、組件優化
1、APR
APR到底能給我們帶來什麽?
1、APR的簡介
APR(Apache Portable Runtime)是一個高可移植庫,它是Apache HTTP Server 2.x的核心。APR有很多用途,包括訪問高級 IO功能(例如sendfile,epoll和OpenSSL),OS級別功能(隨機數生成,系統狀態等等),本地進程管理(共享內存,NT管道和UNIX sockets)。這些功能可以使Tomcat作為一個通常的前臺WEB服務器,能更好地和其它本地web技術集成,總體上讓Java更有效率作為一個高性能web服務器平臺而不是簡單作為後臺容器。
APR的目的如其名稱一樣,主要為上層的應用程序提供一個可以跨越多操作系統平臺使用的底層支持接口庫。在早期的Apache版本中,應用程序本身必須能夠處理各種具體操作系統平臺的細節,並針對不同的平臺調用不同的處理函數。隨著Apache的進一步開發,Apache組織決定將這些通用的函數獨立出來並發展成為一個新的項目。這樣,APR的開發就從Apache中獨立出來,Apache僅僅是使用APR而已。目前APR主要還是由Apache使用,不過由於APR的較好的移植性,因此一些需要進行移植的C程序也開始使用APR。
APR使得平臺細節的處理進行下移。對於應用程序而言,它們根本就不需要考慮具體的平臺,不管是Unix、Linux還是Window,應用程序執行的接口基本都是統一一致的。
因此對於APR而言,可移植性和統一的上層接口是其考慮的一個重點。而APR最早的目的並不是如此,它最早只是希望將Apache中用到的所有代碼合並為一個通用的代碼庫,然而這不是一個正確的策略,因此後來APR改變了其目標。有的時候使用公共代碼並不是一件好事,比如如何將一個請求映射到線程或者進程是平臺相關的,因此僅僅一個公共的代碼庫並不能完成這種區分。
APR的目標則是希望安全合並所有的能夠合並的代碼而不需要犧牲性能。
2、APR的配置
1)下載
APR沒有二進制包可以下載,所以只能下載源代碼版,下載後需要構建,需要下載的文件有:apr-1.5.2.tar.gz、apr-iconv-1.2.1.tar.gz、apr-util-1.5.4.tar.gz(Linux版為例)這三個。
APR的官網為:http://apr.apache.org/
2)安裝
windows下構建源代碼比較麻煩,需要Visual Studio支持。
Linux下構建就相對簡單和熟悉了,只需要執行常規構建命令即可:
./configure --prefix=/usr/local/apr make make install
安裝成功後,APR會默認安裝在 /usr/local/apr目錄下,也可以指定安裝目錄。
apr-iconv安裝時需要指定apr的安裝位置:
./configure --prefix=/usr/local/apr-iconv --with-apr=/usr/local/apr make make install
apr-util安裝時需要指定apr的安裝位置:
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr --with-apr-iconv=/usr/local/apr-iconv/bin/apriconv make make install
3、安裝完成後目錄結構
安裝完成後其實是無法直接使用APR的,想使用APR還需要安裝Tomcat Native,否則Tomcat啟動時會報以下錯誤:
16-May-2016 02:52:42.992 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/local/apr/lib:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2、Tomcat Native
Tomcat Native是 Tomcat可選組件,它可以讓 Tomcat使用 Apache 的 APR包來處理包括文件和網絡IO操作,從而提升性能及兼容性。
1、下載
Tomcat Native可以選擇Windows與Linux版本下載。
Tomcat Native下載地址為:http://tomcat.apache.org/download-native.cgi
2、安裝
(1)Linux/Unix下
安裝Tomcat Native前需要安裝以下組件:
• APR library(我們已安裝)
• OpenSSL libraries
• Java SE Development Kit (JDK)(也已安裝)
OpenSSL libraries安裝通過以下命令:
yum install apr-devel openssl-devel
安裝成功後就可以安裝Tomcat Native了,運行以下命令
下載地址:http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
./configure --with-apr=/usr/local/apr/bin/apr-1-config \ --with-java-home=/usr/java/jdk1.7.0_79 \ --with-ssl=yes \ --prefix=/usr/local/tomcat
註意,--prefix指向的是 Tomcat目錄。
註意,下載後的 Tomcat Native解壓後目錄結構如下:
安裝時需要進入native目錄。
安裝過程中還有可能產生依賴包版本不兼容的問題(一般為openssl版本過低),這時需要卸載舊的依賴,並安裝最新版本
當安裝完成後出現以下類似輸出時,說明安裝已經成功:
Libraries have been installed in: /usr/local/tomcat/lib If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR‘ flag during linking and do at least one of the following: - add LIBDIR to the `LD_LIBRARY_PATH‘ environment variable during execution - add LIBDIR to the `LD_RUN_PATH‘ environment variable during linking - use the `-Wl,-rpath -Wl,LIBDIR‘ linker flag - have your system administrator add LIBDIR to `/etc/ld.so.conf‘ See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ----------------------------------------------------------------------
(2)Windows下
Windows下安裝就異常簡單了,只需要把bin目錄下文件復制到tomcat/bin下即可,如果為64位
3、使用
(1)環境變量配置
使用前需要配置環境變量:
echo "export LD_LIBRARY_PATH=/usr/local/apr/lib">>/etc/profile source /etc/profile
(2)修改Tomcat配置文件
打開conf/server.xml文件,修改Connector 標誌的protocol屬性:
protocol="org.apache.coyote.http11.Http11AprProtocol"
然後添加Listener:
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
保存配置文件後,啟動Tomcat,從日誌中看到以下輸出時,說明全部功能都已配置成功:
16-May-2016 04:28:54.734 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library 1.1.34 using APR version 1.5.2. 16-May-2016 04:28:54.734 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 16-May-2016 04:28:54.739 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized (OpenSSL 1.0.2h 3 May 2016)
至此,APR與 Native都已安裝完成,可以使用,對於 APR與 Native還有很多知識要學習,但不是本文的重點,所以以後有機會還會深入學習。
四、性能測試
Tomcat優化部分我們已經完成,接下來就需要比較一下優化前與優化後的性能對比。
1、Jmeter
Apache JMeter是Apache組織開發的基於Java的壓力測試工具。用於對軟件做壓力測試,它最初被設計用於Web應用測試,但後來擴展到其他測試領域。 它可以用於測試靜態和動態資源,例如靜態文件、Java 小服務程序、CGI 腳本、Java 對象、數據庫、FTP 服務器, 等等。JMeter 可以用於對服務器、網絡或對象模擬巨大的負載,來自不同壓力類別下測試它們的強度和分析整體性能。另外,JMeter能夠對應用程序做功能/回歸測試,通過創建帶有斷言的腳本來驗證你的程序返回了你期望的結果。為了最大限度的靈活性,JMeter允許使用正則表達式創建斷言。
Apache jmeter 可以用於對靜態的和動態的資源(文件,Servlet,Perl腳本,java 對象,數據庫和查詢,FTP服務器等等)的性能進行測試。它可以用於對服務器、網絡或對象模擬繁重的負載來測試它們的強度或分析不同壓力類型下的整體性能。你可以使用它做性能的圖形分析或在大並發負載測試你的服務器/腳本/對象。
Jmeter官網:http://jmeter.apache.org/
1、JMeter的作用
(1)能夠對HTTP和FTP服務器進行壓力和性能測試, 也可以對任何數據庫進行同樣的測試(通過JDBC),Jmeter支持以下服務器協議類型測試:
• Web - HTTP, HTTPS
• SOAP / REST
• FTP
• Database via JDBC
• LDAP
• Message-oriented middleware (MOM) via JMS
• Mail - SMTP(S), POP3(S) and IMAP(S)
• MongoDB (NoSQL)
• Native commands or shell scripts
• TCP
(2)完全的可移植性和100% 純java。
(3)完全 Swing 和輕量組件支持(預編譯的JAR使用 javax.swing.*)包。
(4)完全多線程 框架允許通過多個線程並發取樣和 通過單獨的線程組對不同的功能同時取樣。
(5)精心的GUI設計允許快速操作和更精確的計時。
(6)緩存和離線分析/回放測試結果。
2、JMeter特性
(1)可鏈接的取樣器允許無限制的測試能力。
(2)各種負載統計表和可鏈接的計時器可供選擇。
(3)數據分析和可視化插件提供了很好的可擴展性以及個性化。
(4)具有提供動態輸入到測試的功能(包括JavaScript)。
(5)支持腳本編程的取樣器(在1.9.2及以上版本支持BeanShell)。
在設計階段,JMeter能夠充當HTTP PROXY(代理)來記錄IE/NETSCAPE的HTTP請求,也可以記錄apache等WebServer的log文件來重現HTTP流量。當這些HTTP客戶端請求被記錄以後,測試運行時可以方便的設置重復次數和並發度(線程數)來產生巨大的流量。JMeter還提供可視化組件以及報表工具把量服務器在不同壓力下的性能展現出來。
相比其他HTTP測試工具,JMeter最主要的特點在於擴展性強。JMeter能夠自動掃描其lib/ext子目錄下.jar文件中的插件,並且將其裝載到內存,讓用戶通過不同的菜單調用。
3、JMeter使用
使用Jmeter非常簡單,windows下進入bin目錄直接雙擊jmeter.bat文件即可,Linux下類似,需要運行jmeter.sh文件,Jmeter運行後顯示以下界面:
Jmeter使用起來比較簡單,附件是一個簡單的配置,直接導入即可使用。
2、測試條件
Tomcat版本:8.0.33
測試項目:新創建一個web項目也不用實現任何代碼,只需要部署即可以使用,只有一個index.jsp文件。
JDK版本:jdk1.7.0.67
請求方式:POST
循環次數:100,1000
線程數:10,100,1000
總次數:總次數 = 線程數 * 循環次數
CPU:英特爾 第二代酷睿 i5-2450M(雙核)
內存:8GB
附件時Jmeter的配置文件,可以直接導入使用。
3、測試結果
從部分結果來看優化過的Tomcat會比默認性能及並發處理能力上有提高,但至於參數的配置需要結合硬件及操作系統來不斷調整,所以並不會有一個萬能的參數來使用,需要各位不斷的測試不斷更改。
以下是一個簡單的測試結果,循環100次,線程數分別為10,100,1000:
各位估計已經發現了相同的應用下並不一定某種protocol就一定性能出色,因為Tomcat中的這個測試項目只有一個index.jsp頁面,在較少線程數訪問情況下BIO反應最快,而當線程數達到1000時NIO2性能最出色,而APR中規中矩,雖然這種測試的局限性很大,但也可以反映出:想要找出適合的配置及最佳性能需要結合實際,不斷的測試與改進,最終才能達到一個相對穩定的性能,雖然此時的性能未必是最佳的,但卻是能應對絕大多數情況的。
總結:Tomcat相關優化也只是一個入門介紹,每一種技術之中還是有很多很深奧的知識要去學習,只有不斷的去學習才能不斷的提高。
Tomcat部署及優化