Tomcat作為Web服務器,它的處理性能直接關(guān)系到用戶體驗。
一、Tomcat固定的目錄結(jié)構(gòu)

二、Tomcat的配置
2.1 tomcat端口號的配置
??tomcat端口號的缺省值為8080,如果修改端口號,可以用以下方法:
??找到tomcat目錄下的\conf\server.xml文件中下面的代碼段,修改其中的port即可。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
server.xml是Tomcat算是最基本的配置文件,WEB容器的基本配置都在這里,包括端口、虛擬機、線程池等配置信息。
2.2 如何加大tomcat內(nèi)存
??如果tomcat內(nèi)存不夠用,則會造成內(nèi)存溢出的問題。這時通常會拋出java.lang.OutOfMemoryError: PermGen space異常,是指內(nèi)存的永久保存區(qū)域OutOfMemoryError,解決辦法就是加大內(nèi)存。找到tomcat目錄下的/bin/catalina.sh,在文件的前面,增加如下設置:
??JAVA_OPTS='-Xms[初始化內(nèi)存大小] -Xmx[可以使用的最大內(nèi)存]'
【參數(shù)說明】
-Xms 是指設定程序啟動時占用內(nèi)存大小。一般來講,大點,程序會啟動的 快一點,但是也可能會導致機器暫時間變慢。
-Xmx 是指設定程序運行期間最大可占用的內(nèi)存大小。如果程序運行需要占 用更多的內(nèi)存,超出了這個設置值,就會拋出OutOfMemory 異常。
2.3 如何加大tomcat線程連接數(shù)
在tomcat配置文件server.xml中的配置中,和連接數(shù)相關(guān)的參數(shù)有:
<Connector port="9027"
protocol="HTTP/1.1"
maxHttpHeaderSize="8192"
maxThreads="1000" -- 客戶請求最大線程數(shù)
minSpareThreads="100" --Tomcat初始化時創(chuàng)建的 socket 線程數(shù)
maxSpareThreads="1000" --Tomcat連接器的最大空閑 socket 線程數(shù)
minProcessors="100" -- 服務器創(chuàng)建時的最小處理線程數(shù)
maxProcessors="1000" --最大連接線程數(shù),即:并發(fā)處理的最大請求數(shù),默認值為75
enableLookups="false" --是否反查域名
URIEncoding="utf-8" --URL統(tǒng)一編碼
acceptCount="1000" --允許的最大連接數(shù),應大于等于maxProcessors,默認值為100
redirectPort="8443" --在需要基于安全通道的場合,把客戶請求轉(zhuǎn)發(fā)到基于SSL 的 redirectPort 端口
disableUploadTimeout="true"
connectionTimeout=30000 --網(wǎng)絡連接超時,單位:毫秒。設置為0表示永不超時
/>
其中和最大連接數(shù)相關(guān)的參數(shù)為maxProcessors和acceptCount。如果要加大并發(fā)連接數(shù),應同時加大這兩個參數(shù)。web server允許的最大連接數(shù)還受制于操作系統(tǒng)的內(nèi)核參數(shù)設置,通常Windows是2000個左右,Linux是1000個左右。
2.4 設置tomcat緩存
在tomcat配置文件server.xml中的配置中,和緩存相關(guān)的參數(shù)有:
<Connector port="9027"
protocol="HTTP/1.1"
-- 是否啟用壓縮 on為啟用(文本數(shù)據(jù)壓縮)
compression="on"
-- 啟用壓縮的輸出內(nèi)容大小,這里面默認為2KB,只有當響應報文大小大于這個值的時候才會對報文進行壓縮
compressionMinSize="2048"
-- 配置想壓縮的數(shù)據(jù)類型
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
-- 定義建立客戶連接超時的時間
connectionTimeout="20000"
disableUploadTimeout="true"/>
數(shù)據(jù)被壓縮了,響應速度自然減少了。但是有時候你會發(fā)現(xiàn)compressionMinSize這個配置并不起作用,貌似只要客戶端加了Accept-Encoding: gzip, deflate,響應就是壓縮的,無論響應報文體有多大,這是怎么回事呢?
??Tomcat判斷是否壓縮的的依據(jù)是根據(jù)你響應里的Content-length來的,如果沒有Content-length或者Content-length大于compressionMinSize就進行壓縮。如果你的報文小于compressionMinSize,卻被壓縮了,那就是你的響應報文中并不含有Content-length。
??如果你的響應無論什么大小都被壓縮了,那很有可能就是你在代碼中使用了OutputStream.flush(),或者PrintWriter.flush()。使用flush()的意思是響應開始往外寫了,Content-length已經(jīng)來不及寫了,tomcat會默認使用Transfer-Encoding: chunked形式幫你返回消息,響應肯定是要被壓縮的。
??所以如果你的設置compressionMinSize的沒有生效,很有可能是你的設置的compressionMinSize超出了tomcat的緩沖區(qū)大小,響應默認是chunked的形式返回的,這種情況是肯定壓縮的。
三、Tomcat是如何加載的
Windows下JAVA用到的環(huán)境變量主要有3個,JAVA_HOME、CLASSPATH、PATH。
- JAVA_HOME 指向的是JDK的安裝路徑。
??????JAVA_HOME=C:\jdk1.5.0_06 - PATH 環(huán)境變量原來Windows里面就有,你只需修改一下,使他指向JDK的bin目錄,這樣你在控制臺下面編譯、執(zhí)行程序時就不需要再鍵入一大串路徑了。
??????PATH=%JAVA_HOME%\bin;%PATH%
其中%PATH%是引用以前你設置的PATH環(huán)境變量 - CLASSPATH 環(huán)境變量配置的是java類庫的位置以及執(zhí)行字節(jié)碼文件時查找文件的路徑。
?CLASSPATH=.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
要注意的是最前面的".;",這個是告訴JDK,搜索CLASS時先查找當前目錄的CLASS文件。
Tomcat用到的環(huán)境變量主要有CATALINA_HOME、CATALINA_BASE
- CATALINA_HOME:Tomcat的安裝目錄
- CATALINA_BASE:Tomcat的工作目錄
JVM類加載

當JVM運行過程中,用戶需要加載某些類時,會按照下面的步驟(父類委托機制):
1 用戶自己的類加載器,把加載請求傳給父加載器,父加載器再傳給其父加載器,一直到加載器樹的頂層。
2 最頂層的類加載器首先針對其特定的位置加載,如果加載不到就轉(zhuǎn)交給子類。
3 如果一直到底層的類加載都沒有加載到,那么就會拋出異常。
因此,按照這個過程可以想到,假設兩個包名和類名完全相同的class文件不再同一個jar包,如果一個class文件已經(jīng)被加載java虛擬機里了,那么后面的相同的class文件就不會被加載了。
Tomcat類加載

當tomcat啟動時,會創(chuàng)建幾種類加載器:
1 Bootstrap 引導類加載器
是其他類加載器的父類,它用于加載Java核心庫,并且是唯一一個用本地代碼編寫的類加載器(位于jre/lib/ext下)
2 System 系統(tǒng)類加載器
加載tomcat啟動的類,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。

**3 Common 通用類加載器 **
加載tomcat使用以及應用通用的一些類,位于CATALINA_HOME/lib下,比如servlet-api.jar

4 webapp 應用類加載器
每個應用在部署后,都會創(chuàng)建一個唯一的類加載器。該類加載器會加載位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件。WEB-INF為項目的根目錄,基本地包含一下文件夾:
- classes文件夾:放置已編譯的java類
- config文件夾:放置項目使用的配置文件
- lib文件夾:放置jar庫文件(許多class文件的集合)
- web.xml
當應用需要到某個類時,則會按照下面的順序進行類加載:
1 使用bootstrap引導類加載器加載
2 使用system系統(tǒng)類加載器加載
3 使用應用類加載器在WEB-INF/classes中加載
4 使用應用類加載器在WEB-INF/lib中加載
5 使用common類加載器在CATALINA_HOME/lib中加載
從上面的加載機制我們就可以知道,src下面的java文件優(yōu)先于jar包中的class,這是因為src文件夾中的java類以及webContent中的JSP都會在tomcat啟動時編譯成class文件放置在WEB-INF/classes中;而項目外部引用的jar包則是放置在WEB-INF/lib下。
同時要注意,在同一個文件夾下,jar包是按順序從上到下依次加載,如果已經(jīng)找到,則不會再后續(xù)jar包中進行查找。另外如果在 CATALINA_HOME/lib 以及 WEB-INF/lib 中放置了不同版本的jar包,此時就會導致某些情況下報加載不到類的錯誤。
四、Tomcat的部署方式
(1)靜態(tài)部署
- 將web項目文件件拷貝到webapps 目錄中
- 在server.xml中指定
在tomcat中的conf目錄中,在server.xml中的,<host/>節(jié)點中添加:
<Context path="/hello" docBase="D:\ workspace\hello\WebRoot" debug="0" privileged="true"/>
【參數(shù)說明】
path:虛擬路徑
docBase :應用程序的物理路徑
debug :設定debug level, 0表示提供最少的信息,9表示提供最多的信息
privileged:設置為true的時候,才允許Tomcat的Web應用使用容器內(nèi)的Servlet
- 創(chuàng)建一個Context文件
在conf目錄中,新建 Catalina\localhost目錄,在該目錄中新建一個xml文件,名字不可以隨意取,要和path后的那個名字一致,按照下邊這個path的配置,xml的名字應該就應該是hello(hello.xml),該xml文件的內(nèi)容為:
<Context path="/hello" docBase="D:\ workspace\hello\WebRoot" debug="0" privileged="true"/>
這個方法有個優(yōu)點,可以定義別名。服務器端運行的項目名稱為path,外部訪問的URL則使用XML的文件名。這個方法很方便的隱藏了項目的名稱,對一些項目名稱被固定不能更換,但外部訪問時又想換個路徑,非常有效。
(2)動態(tài)部署
可以用tomcat在線后臺管理器,一般tomcat都打開了,直接上傳war就可以。
五、Tomcat的運行模式
Tomcat如何處理多個用戶同時請求的問題呢?有以下三種方式:
(1)BIO:默認的模式,性能非常低下,沒有經(jīng)過任何優(yōu)化處理和支持。bio模式同步并阻塞,服務器實現(xiàn)模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷。
(2)NIO:同步非阻塞,服務器實現(xiàn)模式為一個請求一個線程,即客戶端發(fā)送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
想運行在該模式下,直接修改server.xml里的Connector節(jié)點,修改protocol為nio:
<Connector port=”80″ protocol=”org.apache.coyote.http11.Http11NioProtocol”
connectionTimeout=”20000″
URIEncoding=”UTF-8″
useBodyEncodingForURI=”true”
enableLookups=”false”
redirectPort=”8443″ />
(3)APR:異步非阻塞,服務器實現(xiàn)模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理。安裝起來最困難,但是從操作系統(tǒng)級別來解決異步的IO問題,大幅度的提高性能。
BIO、NIO、AIO適用場景分析:
BIO方式適用于連接數(shù)目比較小且固定的架構(gòu),這種方式對服務器資源要求比較高,并發(fā)局限于應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。
NIO方式適用于連接數(shù)目多且連接比較短(輕操作)的架構(gòu),比如聊天服務器,并發(fā)局限于應用中,編程比較復雜,JDK1.4開始支持。
AIO方式使用于連接數(shù)目多且連接比較長(重操作)的架構(gòu),比如相冊服務器,充分調(diào)用OS參與并發(fā)操作,編程比較復雜,JDK7開始支持。
六、Tomcat的優(yōu)化
(1)內(nèi)存優(yōu)化
默認情況下Tomcat的相關(guān)內(nèi)存配置較低,這對于一些大型項目顯然是不夠用的,這些項目運行就已經(jīng)耗費了大部分內(nèi)存空間,何況大規(guī)模訪問的情況。可以用-Xmx -Xms -XX:MaxPermSize等參數(shù)對內(nèi)存不同功能塊進行劃分。內(nèi)存分配不足,就導致虛擬機一直處于full GC,從而導致處理能力嚴重下降。
(2)線程優(yōu)化
默認情況下 Tomcat只支持200線程訪問,超過這個數(shù)量的連接將被等待甚至超時放棄,所以我們需要提高這方面的處理能力,優(yōu)化Connector(連接器)。
(3)IO優(yōu)化
在server.xml中
<Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
URIEncoding="UTF-8"
useBodyEncodingForURI="true"
enableLookups="false"
redirectPort="8443" />
實現(xiàn)對Tomcat的IO切換.
(4)利用緩存和壓縮
硬盤主要問題就是讀寫性能,當大量文件進行讀寫時,磁盤極容易成為性能瓶頸。最好的辦法還是利用下面提到的緩存。
對于靜態(tài)頁面最好是能夠緩存起來,這樣就不必每次從磁盤上讀。這里我們采用了Nginx作為緩存服務器,將圖片、css、js文件都進行了緩存,有效的減少了后端tomcat的訪問。
另外,為了能加快網(wǎng)絡傳輸速度,開啟gzip壓縮也是必不可少的。但考慮到tomcat已經(jīng)需要處理很多東西了,所以把這個壓縮的工作就交給前端的Nginx來完成。
(5)采用集群
單個服務器性能總是有限的,最好的辦法自然是實現(xiàn)橫向擴展,那么組建tomcat集群是有效提升性能的手段。