Tomcat系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.htmlhtml
該示例經過設置虛擬主機來提供web服務,由於是入門示例,因此設置極其簡單,只需修改$CATALINA_HOME/conf/server.xml文件爲以下內容便可,本文的tomcat安裝在/usr/local/tomcat下,所以$CATALINA_HOME=/usr/local/tomcat
。其中大部分都採用了默認設置,只是在engine容器中添加了兩個Host容器。前端
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" enableLookups="false" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
</Realm>
<!-- 今後處開始添加如下兩個Host容器做爲虛擬主機 -->
<!-- 定義一個在$CATALINA_HOME以外的虛擬主機 -->
<Host name="www.longshuai.com" appBase="/www/longshuai" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/www/longshuai" reloadable="true" />
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="longshuai_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!-- 定義一個在$CATALINA_HOME/webapps下的虛擬主機 -->
<Host name="www.xiaofang.com" appBase="webapps/xiaofang" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="" reloadable="true" />
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="xiaofang_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!-- 默認虛擬主機localhost,可不修改 -->
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
除了engine中定義的默認localhost虛擬主機,另外佈置了兩個虛擬主機www.longshuai.com和www.xiaofang.com,它們的程序目錄分別爲/www/longshuai和$CATALINA_HOME/webapps/xiaofang,因此須要提早創建好這兩個目錄。另外,在context中定義了docBase,對於uri路徑/xuexi,它的文件系統路徑分別爲/www/longshuai/xuexi目錄和$CATALINA_HOME/webapps/xiaofang/xuexi,因此也要在上面兩個程序目錄中定義好xuexi目錄。除此以外,還分別爲這3個虛擬主機定義了日誌,它們的路徑爲相對路徑logs,相對於$CATALINA_HOME。java
再提供appBase目錄和docBase目錄。mysql
mkdir -p /www/longshuai/xuexi
mkdir -p /usr/local/tomcat/webapps/xiaofang/xuexi
再提供測試用的index.jsp文件。內容大體以下,分別複製到如下四個目錄中:
/www/longshuai/
/www/longshuai/xuexi/
/usr/local/tomcat/webapps/xiaofang/
/usr/local/tomcat/webapps/xiaofang/xuexi nginx
並將out.println的輸出內容分別稍做修改,使可以區分讀取的是哪一個index.jsp。web
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<body>
<% out.println("hello world from longshuai Root"); %>
</body>
</html>
最後重啓catalina。sql
catalina.sh stop catalina.sh start
再測試主機上添加www.{longshuai,xiaofang}.com的host記錄。例如在windows上,在C:\Windows\System32\drivers\etc\hosts中添加以下記錄:數據庫
192.168.100.22 www.longshuai.com www.xiaofang.com
在瀏覽器中進行測試,結果以下:apache
以下兩圖:上面的圖是tomcat組件體系的簡圖,下面的圖是Service組件細化後的圖。windows
tomcat高度模塊化,各個模塊之間有嵌套的父子關係。若是使用配置文件來描述,能夠大體簡化爲以下:
<server>
<service>
<connector PORT />
<engine>
<host name=www.a.com appBase=/www/a >
<context path="" docBase=/www/a />
<context path="/xuexi" docBase=/www/a/xuexi />
</host>
<host>
<context />
</host>
</engine>
</service>
</server>
其中:
server
組件是管理tomcat實例的組件,能夠監聽一個端口,今後端口上能夠遠程向該實例發送shutdown關閉命令。service
組件是一個邏輯組件,用於綁定connector和container,有了service表示能夠向外提供服務,就像是通常的daemon類服務的service。能夠認爲一個service就啓動一個JVM,更嚴格地說,一個engine組件纔對應一個JVM(定義負載均衡時,jvmRoute就定義在Engine組件上用來標識這個JVM),只不過connector也工做在JVM中。connector
組件是監聽組件,它有四個做用:
container
是容器,它是一類組件,在配置文件(如server.xml)中沒有體現出來。它包含4個容器類組件:engine容器、host容器、context容器和wrapper容器。engine
容器用於從connector組件處接收已創建的TCP鏈接,還用於接收客戶端發送的http請求並分析請求,而後按照分析的結果將相關參數傳遞給匹配出的虛擬主機。engine還用於指定默認的虛擬主機。host
容器定義虛擬主機,因爲tomcat主要是做爲servlet容器的,因此爲每一個webapp指定了它們的根目錄appBase。context
容器主要是根據path和docBase獲取一些信息,將結果交給其內的wrapper組件進行處理(它提供wrapper運行的環境,因此它叫上下文context)。通常來講,都採用默認的標準wrapper類,所以在context容器中幾乎不會出現wrapper組件。wrapper
容器對應servlet的處理過程。它開啓servlet的生命週期,根據context給出的信息以及解析web.xml中的映射關係,負責裝載相關的類,初始化servlet對象init()、執行servlet代碼service()以及服務結束時servlet對象的銷燬destory()。executor
組件爲每一個Service組件提供線程池,使得各個connector和Engine能夠從線程池中獲取線程處理請求,從而實現tomcat的併發處理能力。必定要注意,Executor的線程池大小是爲Engine組件設置,而不是爲Connector設置的,Connector的線程數量由Connector組件的acceptorThreadCount屬性來設置。若是要在配置文件中設置該組件,則必須設置在Connector組件的前面,以便在Connector組件中使用`executor`屬性來引用配置好的Executor組件。若是不顯式設置,則採用Connector組件上的默認配置,默認配置以下:
根據上面描述的tomcat組件體系結構,處理請求的大體過程其實很容易推導出來:
Client(request)-->Connector-->Engine-->Host-->Context-->Wrapper(response data)-->Connector(response header)-->Client
撇開tomcat做爲servlet容器的行爲。它和apache、nginx的功能大體都能對應上。例如以nginx爲例,如下是nginx提供web服務時的配置結構:
server {
listen PORT;
server_name www.a.com; # 對應於<host name=www.a.com>
location / { # 對應於context path=""
root html; # 對應於docBase
}
location /xuexi { # 對應於context path="/xuexi"
root html/xuexi;
}
}
connetcor組件相似於nginx的listen指令。host容器相似於nginx的server指令,host容器中的name屬性至關於nginx的server_name指令。engine組件則沒有對應配置項,不過在nginx一樣有engine的功能,例如默認的虛擬主機,分析URL來判斷請求交給哪一個虛擬主機處理等。context容器至關於location指令,context容器的path屬性至關於location的uri匹配路徑,docBase至關於location的中的root指令,即DocumentRoot。
tomcat做爲簡單的web服務程序大體如此,但它的核心畢竟是處理servlet和jsp,它必須得管理好每一個webapp。所以,對於tomcat來講,必需要掌握部署webapp的方式。在tomcat上部署webapp時,必需要理解context的概念。對於tomcat而言,每一個context都應該算是一個webapp,其路徑由docBase決定,該目錄存放的是歸檔的war文件或未歸檔的webapp相關文件,而host容器中的appBase則是虛擬主機整理webapp的地方,一個appBase下能夠有多個webapp,即多個context。
這兩貨雖然意義很明確,但"潛規則"很嚴重。如下面的配置爲例。
<host name=www.a.com appBase=/www/a >
<context path="" docBase=/www/a />
<context path="/xuexi" docBase=/www/a/xuexi />
</host>
appBase是虛擬主機存放webapp的目錄,它能夠是相對路徑,也能夠是絕對路徑。若是是相對路徑,則相對於$CATALINA_HOME,嚴格並準確地說是$CATALINA_BASE。
path是URI的匹配路徑,至關於nginx的location後的路徑。tomcat要求每一個虛擬主機必須配置一個空字符串的path,該條context做爲URI沒法被明確匹配時的默認context,它至關於nginx中location / {}
的做用。
docBase則是每一個webapp的存放目錄(或者是已歸檔的war文件),它能夠是相對路徑,也能夠是絕對路徑,提供相對路徑時它相對於appBase。該目錄通常在appBase的目錄下,但並不規定必定要放在appBase下。對於web服務來講,它至關於nginx的root指令,但對於webapp來講,一個context就至關於一個webapp,而docBase正是webapp的路徑。
"潛規則"在於默認的context如何提供。有如下幾種狀況:
<context path="" docBase=webappPATH>
,此時默認context的處理路徑爲webappPATH。<context path="">
,但卻沒給定docBase屬性,此時該默認context處理路徑爲appBase/ROOT目錄,注意ROOT爲大寫。path=""
的context時,即host容器中沒有明確的path="",此時將隱式定義一個默認context,處理路徑爲appBase/ROOT目錄。context path context name 推斷出的docBase路徑
--------------------------------------------------
/foo /foo foo
/foo/bar /foo/bar foo/bar
Empty String Empty String ROOT
顯然,沒有給定path=""或缺乏docbase時,都以ROOT做爲目錄。如下是幾個定義示例:
# 虛擬主機中沒有定義任何context,將以appBase下的ROOT做爲默認處理路徑
<Host appBase="webapps">
</Host>
# 沒有定義path=""的context,但定義了path非空的context,也將以ROOT做爲默認處理路徑
# 若是下面的Context容器中省略docBase屬性,則推斷出該context的docBase路徑爲appBase/xuexi
<Host appBase="webapps">
<Context path="/xuexi" docBase="webappPATH" />
</Host>
# 某個context定義了path="",該context將做爲默認context
# 但該默認context若是沒有定義docBase,將推斷出其docBase路徑爲appBase/ROOT
<Host appBase="webapps">
<Context path="" docBase="webappPATH" />
</Host>
# 某個context定義了path="",該context將做爲默認context
# 下面的默認context明肯定義了docBase
<Host appBase="webapps">
<Context path="" docBase="webappPATH" />
</Host>
舉個直觀的例子,若是某個Host配置以下。
<Host name="www.xiaofang.com" appBase="/www/xiaofang" unpackWARs="true" autoDeploy="true">
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
</Host>
那麼瀏覽器訪問http://www.xiaofang.com:8080/xuexi/
將請求/www/xiaofang/xuexi/index.jsp
。
因爲沒有定義path=""的Context組件,所以瀏覽器訪問http://www.xiaofang.com:8080
將請求/www/xiaofang/ROOT/index.jsp
。注意,是ROOT目錄。
若是加上<Context path="" docBase="" reloadable="true" />
,則訪問http://www.xiaofang.com:8080
將請求/www/xiaofang/index.jsp
。注意,不是ROOT目錄,而是相對於appBase的根目錄,即/www/xiaofang。
儘管本文解釋了一大堆關於appBase和docBase的設置,但通常都會採用大衆所熟知的配置方式:appBase設置爲"webapps",即$CATALINA_HOME/webapps,而docBase設置爲webapps下的webapp應用名。這樣配置不只符合eclipse部署webapp時默認的部署目錄結構(eclipse部署應用時,將WebContent下的內容複製到docBase下,將servlet java源代碼編譯後的class文件複製到WEB-INF/classes目錄下),更利於維護webapp和相關配置。例如:
<Context docBase="MyWeb" path="/MyWeb" reloadable="true" />
<Context docBase="SecondWeb" path="/SecondWeb" reloadable="true" />
<Context docBase="WEB" path="/WEB" reloadable="true" />
但這樣的配置有個缺點,由於項目名稱通常都會帶有大寫字母,使得在瀏覽器訪問時,也要帶有大寫字母。例如輸入http://www.a.com/MyWeb/index.jsp
。所以,可採用另外一種配置方式:設置Host的appBase爲webapps下的某個目錄,而後在path上配置uri匹配路徑。以下:
<Host name="www.xiaofang.com" appBase="webapps/MyWeb" unpackWARs="true" autoDeploy="true">
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Context path="" docBase="" reloadable="true" />
</Host>
webapp有特定的組織格式,是一種層次型目錄結構,一般包含了servlet代碼文件、jsp頁面文件、類文件、部署描述符文件等等。
這些文件多是以目錄的形式存放,也可能會打包成各類歸檔格式的文件,如jar、war等。但jsp有規定,在web應用程序的根目錄下,通常要有下面幾個目錄:
每一個webapp要想被tomcat加載,一種方法是程序目錄放在$catalina.home/webapps下,另外一種方式是配置該webapp相關的context配置,使tomcat能找到此webapp。正如前文所說,webapp目錄通常都會放在$catalina.home/webapps下。
簡單部署示例:
(1)對於war類歸檔程序:將歸檔文件複製到$CATALINA_BASE/webapps/目錄中,並重啓tomcat便可,tomcat會自動展開war歸檔。例如官方提供了一個sample.war做爲tomcat學習初級示例( https://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war ),下載後只需將其放入webapps下便可。
(2)在測試tomcat的過程當中,不少時候是未歸檔程序,這時能夠手動建立目錄來實現部署。須要建立的目錄有webapps/yourapp,此目錄下還要建立WEB-INF目錄,在WEB-INF目錄中還要建立classes和lib目錄。而後將jsp文件放在對應目錄下便可,如寫一個測試的index.jsp放在yourapp目錄下。而對於已經開發完畢的webapp,由於eclipse在發佈測試webapp時已經設置好目錄,所以只要將webapp的目錄複製到webapps目錄下便可。
tomcat配置文件中配置的是各個組件的屬性,全局配置文件爲$CATALINA_HOME/conf/server.xml,主要的組件有如下幾項:Server,Service,Connector,Engine,Host,Alias,Context,Valve等。配置完配置文件後須要重啓tomcat,但在啓動後必定要檢查tomcat是否啓動成功,由於即便出錯,不少時候它都不會報錯,可從監聽端口判斷。
配置方法見官方手冊,在頁面的左邊有各個組件的連接。
tomcat的配置文件都是xml文件,如下是xml文件的常見規則:
<?xml version="1.0" encoding="UTF-8"?>
。<!-- XXX -->
,這能夠是單行註釋,也能夠多行註釋,只要先後註釋符號能對應上,中間的內容都是註釋。<!-- 單行定義的方式 -->
<NAME key=value />
<!-- 多行定義的方式 -->
<NAME key=value>
</NAME>
下面個組件的配置中有些地方使用了相對於$CATALINA_BASE的相對路徑,它和$CATALINA_HOME小有區別。若是隻有一個tomcat實例,則它們是等價的,都是tomcat的安裝路徑。若是有多個tomcat實例,則$CATALINA_HOME表示的是安裝路徑,而$CATALINA_BASE表示的是各實例所在根目錄。關於tomcat多實例,見running.txt中對應的說明。
server組件定義的是一個tomcat實例。默認定義以下:
<Server port="8005" shutdown="SHUTDOWN">
</Server>
它默認監聽在8005端口以接收shutdown命令。要啓用多個tomcat實例,將它們監聽在不一樣的端口便可。這個端口的定義爲管理員提供一個關閉實例的便捷途徑,能夠直接telnet至此端口使用SHUTDOWN命令關閉此實例。不過基於安全角度的考慮,一般不容許遠程進行。
Server的相關屬性:
className
:用於實現此組件的java類的名稱,這個類必須實現接口org.apache.catalina.Server。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardServer;address
:監聽端口綁定的地址。如不指定,則默認爲Localhost,即只能在localhost上發送SHUTDOWN命令;port
:接收shutdown指令的端口,默認僅容許經過本機訪問,默認爲8005;shutdown
:經過TCP/IP鏈接發往此Server用於實現關閉tomcat實例的命令字符串。在server組件中可嵌套一個或多個service組件。
定義了service就能提供服務了。service組件中封裝connector和container,它同時也表示將此service中的connector和container綁定起來,即由它們組成一個service向外提供服務。默認定義以下:
<Service name="Catalina">
</Service>
Service相關的屬性:
className
:用於實現service的類名,這個類必須實現org.apache.catalina.Service接口。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardService。name
:此service的顯示名稱,該名稱主要用於在日誌中進行標識service。通常來講可有可無,默認爲Catalina。執行器定義tomcat各組件之間共享的線程池。在之前,每一個connector都會獨自建立本身的線程池,但如今,能夠定義一個線程池,各組件均可以共享該線程池,不過主要是爲各connector之間提供共享。注意,executor建立的是共享線程池,若是某個connector不引用executor建立的線程池,那麼該connector仍會根據本身指定的屬性建立它們本身的線程池。
鏈接器必需要實現org.apache.catalina.Executor接口。它是一個嵌套在service組件中的元素,爲了挑選所使用的connector,該元素還必須定義在connector元素以前。
默認的定義以下:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
其中該組件的屬性有:
className
:用於實現此組件的java類的名稱,這個類必須實現接口org.apache.catalina.Executor。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardThreadExecutor;name
:該線程池的名稱,其餘組件須要使用該名稱引用該線程池。標準類的屬性包括:
threadPriority
:線程優先級,默認值爲5。daemon
:線程是否以daemon的方式運行,默認值爲true。namePrefix
:執行器建立每一個線程時的名稱前綴,最終線程的名稱爲:namePrefix+threadNumber。maxThreads
:線程池激活的最大線程數量。默認值爲200。minSpareThreads
:線程池中最少空閒的線程數量。默認值爲25。maxIdleTime
:在空閒線程關閉前的毫秒數。除非激活的線程數量小於或等於minSpareThreads的值,不然會有空閒線程的出現。默認值爲60000,即空閒線程須要保留1分鐘的空閒時間才被殺掉。maxQueueSize
:可執行任務的最大隊列數,達到隊列上限時的鏈接請求將被拒絕。prestartminSpareThreads
:在啓動executor時是否當即建立minSpareThreads個線程數,默認爲false,即在須要時才建立線程。例如在connector中指定所使用的線程池,方式以下:
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
鏈接器用於接收客戶端發送的請求並返回響應給客戶端。一個service中能夠有多個connector。有多種connector,常見的爲http/1.1,http/2和ajp(apache jserv protocol)。在tomcat中,ajp鏈接協議類型專用於tomcat前端是apache反向代理的狀況下。
所以tomcat能夠扮演兩種角色:
Tomcat應該考慮工做情形併爲相應情形下的請求分別定義好須要的鏈接器才能正確接收來自於客戶端的請求。
此處暫先介紹HTTP/1.1鏈接器的屬性設置。ajp後文再作介紹。
HTTP鏈接器表示支持HTTP/1.1協議的組件。設置了該鏈接器就表示catalina啓用它的獨立web服務功能,固然,確定也提供它必須的servlets和jsp執行功能。在一個service中能夠配置一個或多個鏈接器,每一個鏈接器均可以將請求轉發給它們相關聯的engine以處理請求、建立響應。
每一個流入的請求都須要一個獨立的線程來接收。當併發請求數量超出maxThreads指定的值時,多出的請求將被堆疊在套接字中,直到超出acceptCount指定的值。超出accpetCount的請求將以"connection refused"錯誤進行拒絕。
默認的定義以下:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
HTTP鏈接器的屬性實在太多,詳細配置方法見官方手冊。一般定義HTTP鏈接器時必須定義的屬性只有"port"。
address
:指定鏈接器監聽的地址,默認爲全部地址,即0.0.0.0。maxThreads
:支持的最大併發鏈接數,默認爲200;若是引用了executor建立的共享線程池,則該屬性被忽略。acceptCount
:設置等待隊列的最大長度;一般在tomcat全部處理線程均處於繁忙狀態時,新發來的請求將被放置於等待隊列中;maxConnections
:容許創建的最大鏈接數。acceptCount和maxThreads是接受鏈接的最大線程數。存在一種狀況,maxConnections小於acceptCount時,超出maxConnections的鏈接請求將被接收,但不會與之創建鏈接。port
:監聽的端口,默認爲0,此時表示隨機選一個端口,一般都應該顯式指定監聽端口。protocol
:鏈接器使用的協議,用於處理對應的請求。默認爲HTTP/1.1,此時它會自動在基於Java NIO或APR/native鏈接器之間進行切換。定義AJP協議時一般爲AJP/1.3。redirectPort
:若是某鏈接器支持的協議是HTTP,當接收客戶端發來的HTTPS請求時,則轉發至此屬性定義的端口。connectionTimeout
:等待客戶端發送請求的超時時間,單位爲毫秒,默認爲60000,即1分鐘;注意,這時候鏈接已經創建。keepAliveTimeout
:長鏈接狀態的超時時間。超出該值時,長鏈接將關閉。enableLookups
:是否經過request.getRemoteHost()進行DNS查詢以獲取客戶端的主機名;默認爲true,應設置爲false防止反解客戶端主機;compression
:是否壓縮數據。默認爲off。設置爲on時表示只壓縮text文本,設置爲force時表示壓縮全部內容。應該在壓縮和sendfile之間作個權衡。useSendfile
:該屬性爲NIO的屬性,表示是否啓用sendfile的功能。默認爲true,啓用該屬性將會禁止compression屬性。當協議指定爲HTTP/1.1時,默認會自動在NIO/APR協議處理方式上進行按需切換。如要顯式指定協議,方式以下:
<connector port="8080" protocol="HTTP/1.1">
<connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol">
其中NIO是C/C++的非阻塞IO複用模型在JAVA中的IO實現,NIO2即AIO是異步NIO,即異步非阻塞IO:
NioProtocol :non blocking Java NIO connector
Nio2Protocol:non blocking Java NIO2 connector
AprProtocol :the APR/native connector
它們之間的異同點以下表所示:
Java Nio Connector | Java Nio2 Connector | APR/native Connector | |
---|---|---|---|
Classname | Http11NioProtocol | Http11Nio2Protocol | Http11AprProtocol |
Tomcat Version | 6.x onwards | 8.x onwards | 5.5.x onwards |
Support Polling | YES | YES | YES |
Polling Size | maxConnections | maxConnections | maxConnections |
Read Request Headers | Non Blocking | Non Blocking | Non Blocking |
Read Request Body | Blocking | Blocking | Blocking |
Write Response Headers and Body | Blocking | Blocking | Blocking |
Wait for next Request | Non Blocking | Non Blocking | Non Blocking |
SSL Support | Java SSL or OpenSSL | Java SSL or OpenSSL | OpenSSL |
SSL Handshake | Non blocking | Non blocking | Blocking |
Max Connections | maxConnections | maxConnections | maxConnections |
下面是一個定義了多個屬性的SSL鏈接器:
<Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
engine是service組件中用來分析協議的引擎機器,它從一個或多個connector上接收請求,並將請求交給對應的虛擬主機進行處理,最後返回完整的響應數據給connector,經過connector將響應數據返回給客戶端。
只有一個engine元素必須嵌套在每一個service中,且engine必須在其所須要關聯的connector以後,這樣在engine前面的connector均可以被此engine關聯,而在engine後面的connector則被忽略,由於一個service中只容許有一個engine。
定義方式大體以下:
<Engine name="Catalina" defaultHost="localhost">
</Engine>
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA">
</Engine>
經常使用的engine屬性有:
className
:實現engine的類,該類必須實現org.apache.catalina.Engine接口。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardEngine。defaultHost
:指定處理請求的默認虛擬主機。在Engine中定義的多個虛擬主機的主機名稱中至少有一個跟defaultHost定義的主機名稱同名。name
:Engine組件的名稱,用於記錄日誌和錯誤信息,可有可無的屬性,可隨意給定。jvmRoute
:在啓用session粘性時指定使用哪一種負載均衡的標識符。全部的tomcat server實例中該標識符必須惟一,它會追加在session標識符的尾部,所以能讓前端代理老是將特定的session轉發至同一個tomcat實例上。engine是容器中的頂級子容器,其內能夠嵌套一個或多個Host做爲虛擬主機,且至少一個host要和engine中的默認虛擬主機名稱對應。除了host,還能夠嵌套releam和valve組件。
host容器用來定義虛擬主機。engine從connector接收到請求進行分析後,會將相關的屬性參數傳遞給對應的(篩選方式是從請求首部的host字段和虛擬主機名稱進行匹配)虛擬host進行處理。若是沒有合適的虛擬主機,則傳遞給默認虛擬主機。所以每一個容器中必須至少定義一個虛擬主機,且必須有一個虛擬主機和engine容器中定義的默認虛擬主機名稱相同。
大體定義方式以下:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
</Host>
經常使用屬性說明:
className
:實現host容器的類,該類必須實現org.apache.catalina.Host接口。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardHost。name
:虛擬主機的主機名,忽略大小寫(初始化時會自動轉換爲小寫)。可使用前綴星號通配符,如"*.a.com"。使用了星號前綴的虛擬主機的匹配優先級低於精確名稱的虛擬主機。appBase
:此Host的webapps目錄,即webapp部署在此虛擬主機上時的存放目錄。包括非歸檔的web應用程序目錄和歸檔後的WAR文件的目錄。使用相對路徑時基於$CATALINA_BASE。xmlBase
:部署在此虛擬主機上的context xml目錄。startStopThreads
:啓動context容器時的並行線程數。若是使用了自動部署功能,則再次部署或更新時使用相同的線程池。autoDeploy
:在Tomcat處於運行狀態時放置於appBase目錄中的應用程序文件是否自動進行deploy或自動更新部署狀態。這等於同時開啓了deployOnStartup屬性和reload/redeploy webapp的功能。觸發自動更新時將默認重載該webapp。默認爲true。unpackWars
:在執行此webapps時是否先對歸檔格式的WAR文件解壓再運行,設置爲false時則直接執行WAR文件;默認爲true。設置爲false時會損耗性能。workDir
:該虛擬主機的工做目錄。每一個webapp都有本身的臨時IO目錄,默認該工做目錄爲$CATALINA_BASE/work。大多數時候都只需設置虛擬主機名稱name和appBase屬性便可,其他採用默認,默認時會自動部署webapp。有時候還須要管理多個站點名稱,即主機別名。可使用Alias爲Host指定的主機名定義主機別名。如:
<Host name="web.a.com" appBase="webapps" unpackWARs="true">
<Alias>www.a.com</Alias>
</Host>
自動部署指的是自動裝載webapp以提供相關webapp的服務。
connector和container是整個tomcat的心臟,而context則是container的心臟,更是tomcat心臟的心臟。它是真正管理servlet的地方,它的配置影響了servlet的工做方式。
一個context表明一個webapp。servlet中規定,每一個webapp都必須基於已歸檔的WAR(WEB application archive)文件或基於非歸檔相關內容所在目錄。
catalina基於對請求URI與context中定義的path進行最大匹配前綴的規則進行挑選,從中選出使用哪一個context來處理該HTTP請求。這至關於nginx的location容器,catalina的path就至關於location的path,它們的做用是相同的。
每一個context都必須在虛擬主機容器host中有一個惟一的context name。context的path不須要惟一,由於容許同一個webapp不一樣版本的共存部署。此外,必需要有一個context的path爲0長度的字符串(如<Context path="" docBase="ROOT"/>
),該context是該虛擬主機的默認webapp,用於處理全部沒法被虛擬主機中全部context path匹配的請求(固然,不定義也能夠,此時將自動隱式提供,見前文所述)。
關於context name,它是從context path推斷出來的,不只如此,其他幾個屬性如context basefile name也是由此推斷出來的。規則以下:
例如:
context path context name basefile name deploy examples
-----------------------------------------------------------------
/foo /foo foo foo.xml,foo.war,foo
/foo/bar /foo/bar foo#bar foo#bar.xml,foo#bar.war,foo#bar
Empty String Empty String ROOT ROOT.xml,ROOT.war,ROOT
配置context時,強烈建議不要定義在server.xml中,由於定義在conf/server.xml中時,只能經過重啓tomcat來重載生效,也就是說沒法自動部署應用程序了。雖然說官方如此推薦,但大多數人出於習慣和方便,仍是會直接寫在server.xml中,這並無什麼問題,無非是重啓一下而已。
能夠考慮定義在/META-INF/context.xml中,若是此時設置了copyXML屬性,在部署時會將此context.xml複製到$CATALINA_BASE/conf/enginename/hostname/下,並重命名爲"basefile name.xml"。也能夠直接定義在$CATALINA_BASE/conf/enginename/hostname/下的.xml文件中,該路徑的xml優先級高於/META-INF/context.xml。
還能夠定義默認的context.xml文件,包括兩種:(1)定義在$CATALINA_BASE/conf/context.xml中,該默認context對全部webapp都生效;(2)定義在$CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default中,該默認context只對該虛擬主機中的全部webapp生效。
定義方式大體以下:
<Host name="www.a.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT"/>
<Context path="/bbs" docBase="web/bbs" reloadable="true"/>
</Host>
其中第一個context的path爲空字符串,表示它是默認的context。當瀏覽器中輸入www.a.com時,因爲沒法匹配第二個context,因此被默認即第一個context處理,當瀏覽器中輸入www.a.com/bbs時,將被第二個context處理,它將執行web/bbs所對應的webapp,並返回相關內容。
在context容器中能夠定義很是多的屬性,詳細內容見官方手冊,如下是常見的幾個屬性:
className
:實現host容器的類,該類必須實現org.apache.catalina.Context接口。不給定該屬性時將採用默認的標準類org.apache.catalina.core.StandardContext。cookies
:默認爲true,表示啓用cookie來標識session。docBase
:即DocumentRoot,是該webapp的context root,即歸檔WAR文件所在目錄或非歸檔內容所在目錄。能夠是絕對路徑,也能夠是相對於該webapp appBase的相對路徑。path
:定義webapp path。注意,當path=""時,表示默認的context;另外只有在server.xml中才須要定義該屬性,其餘全部狀況下都不能定義該屬性,由於會根據docBase和context的xml文件名推斷出path。reloadable
:是否監控/WEB-INF/class和/WEB-INF/lib兩個目錄中文件的變化,變化時將自動重載。在測試環境下該屬性很好,但在真實生產環境部署應用時不該該設置該屬性,由於監控會大幅增長負載,所以該屬性的默認值爲false。wrapperClass
:實現wrapper容器的類,wrapper用於管理該context中的servlet,該類必須實現org.apache.catalina.Wrapper接口,若是不指定該屬性則採用默認的標準類。xmlNamespaceAware
:和web.xml的解析方式有關。默認爲true,設置爲false能夠提高性能。xmlValidation
:和web.xml的解析方式有關。默認爲true,設置爲false能夠提高性能。realm定義的是一個安全上下文,就像是以哪一種方式存儲認證時的用戶和組相關的數據庫。有多種方式能夠實現數據存放:
下面是一個常見的使用UserDatabase的配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
下面是一個使用JDBC方式獲取用戶認證信息的配置:
<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99" driverName="org.gjt.mm.mysql.Driver" connectionURL="jdbc:mysql://localhost/authority" connectionName="test" connectionPassword="test" userTable="users" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles" roleNameCol="role_name" />
Valve中文意思是閥門,相似於過濾器,它能夠工做於Engine和Host/Context之間、Host和Context之間以及Context和Web應用程序的某資源之間。一個容器內能夠創建多個Valve,並且Valve定義的次序也決定了它們生效的次序。
有多種不一樣的Valve:
其中RemoteHostValve和RemoteAddrValve能夠分別用來實現基於主機名稱和基於IP地址的訪問控制,控制自己能夠經過allow或deny來進行定義,這有點相似於Apache的訪問控制功能。以下面的Valve實現了僅容許本機訪問/probe:
<Context privileged="true" path="/probe" docBase="probe">
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1"/>
</Context>
其中相關屬性定義有:
另一個經常使用的Valve爲AccessLogValve,定義方式大體以下:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
其中prefix和suffix表示日誌文件的前綴名稱和後綴名稱。pattern表示記錄日誌時的信息和格式。