本文目錄:1. 入門示例:虛擬主機提供web服務2. tomcat體繫結構基本說明3. tomcat的appBase和docBase詳細說明 4. tomcat進階:tomcat配置文件server.xml詳解 4.1 頂級元素server 4.2 頂級元素service 4.3 執行器execut ...
本文目錄:
1. 入門示例:虛擬主機提供web服務
2. tomcat體繫結構基本說明
3. tomcat的appBase和docBase詳細說明
4. tomcat進階:tomcat配置文件server.xml詳解
4.1 頂級元素server
4.2 頂級元素service
4.3 執行器executor
4.4 連接器connector
4.5 容器類engine
4.6 容器類host
4.7 容器類context
4.8 被嵌套類realm
4.9 被嵌套類valve
1. 入門示例:虛擬主機提供web服務
該示例通過設置虛擬主機來提供web服務,因為是入門示例,所以設置極其簡單,只需修改$CATALINA_HOME/conf/server.xml文件為如下內容即可。其中大部分都採用了預設設置,只是在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容器作為虛擬主機 -->
<Host name="www.longshuai.com" appBase="/www/webapps/longshuai"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/www/webapps/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>
<Host name="www.xiaofang.com" appBase="/www/webapps/xiaofang"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/www/webapps/xiaofang" 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>
<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和/www/xiaofang,所以需要提前建立好這兩個目錄。另外,在context中定義了docBase,對於uri路徑/xuexi,它的文件系統路徑為/www/{longshuai,xiaofang}/xuexi目錄,所以也要在上面兩個程式根目錄中定義好xuexi目錄。除此之外,還分別為這3個虛擬主機定義了日誌,它們的路徑為相對路徑logs,相對於$CATALINA_HOME。
再提供appBase目錄和docBase目錄。
mkdir -p /www/{longshuai,xiaofang}/xuexi
再提供測試用的index.jsp文件。內容大致如下,分別複製到/www/{longshuai,xiaofang}/和/www/{longshuai,xiaofang}/xuexi/下,並將out.println的輸出內容分別稍作修改,使能夠區分讀取的是哪個index.jsp。
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<body>
<% out.println("hello world from longshuai Root"); %>
</body>
</html>
最後重啟catalina。
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
在瀏覽器中進行測試,結果如下:
2. tomcat體繫結構基本說明
如下圖:
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和containor,有了service表示可以向外提供服務,就像是一般的daemon類服務的service。
connector組件是服務監聽組件,用於監聽外界請求並建立TCP連接,然後將連接交給containor,之後可以從此連接傳輸數據,例如接收http請求,發送http響應等。
containor是容器,在配置文件中沒有體現出來,它包含4個容器類組件:engine容器、host容器、context容器和wrapper容器。
engine容器用於從connector組件處接收已建立的TCP連接,還用於接收客戶端發送的http請求並分析請求,然後按照分析的結果將相關參數傳遞給匹配出的虛擬主機。engine還用於指定預設的虛擬主機。
host容器定義虛擬主機,由於tomcat主要是作為servlet容器的,所以為每個web應用程式指定了它們的根目錄appBase。
context容器對應servlet容器的處理過程。還可以指定相關的wrapper容器類,當然一般都採用預設的標準wrapper類。
最後當請求處理完畢後,context將響應數據返回給host,再返回給engine,再返回給connector,最後返回給客戶端。
撇開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。
3. tomcat的appBase和docBase詳細說明
這兩貨雖然意義很明確,但"潛規則"很嚴重。以下麵的配置為例。
<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目錄。 - 定義了path但沒有定義docBase屬性時,docBase將根據path推斷出它的路徑。推斷的規則如下:
context path context name 推斷出的docBase路徑
--------------------------------------------------
/foo /foo foo
/foo/bar /foo/bar foo/bar
Empty String Empty String ROOT
以下是幾個定義示例:
# 虛擬主機中沒有定義任何context,將以appBase下的ROOT作為預設處理路徑
<Host appBase="webapps">
</Host>
# 沒有定義path=""的context,但定義了path非空的context,也將以ROOT作為預設處理路徑
# 如果下麵的Context容器中省略docBase屬性,則推斷出其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>
4. tomcat配置文件server.xml詳解
tomcat配置文件中配置的是各個組件的屬性,全局配置文件為$CATALINA_HOME/conf/server.xml,主要的組件有以下幾項:Server,Service,Connector,Engine,Host,Alias,Context,Valve等。配置完配置文件後需要重啟tomcat,但在啟動後一定要檢查tomcat是否啟動成功,因為即使出錯,很多時候它都不會報錯,可從監聽埠判斷。
配置方法見官方手冊,在頁面的左邊有各個組件的鏈接。
tomcat的配置文件都是xml文件,以下是xml文件的常見規則:
- 文件第一行設置xml標識,表示該文件是xml格式的文件。例如
<?xml version="1.0" encoding="UTF-8"?>
。 - xml文件的註釋方法為
<!-- XXX -->
,這可以是單行註釋,也可以多行註釋,只要前後註釋符號能對應上,中間的內容都是註釋。 - 定義屬性時有兩種方式:單行定義和多行定義。例如:
<!-- 單行定義的方式 -->
<NAME key=value />
<!-- 多行定義的方式 -->
<NAME key=value>
</NAME>
下麵個組件的配置中有些地方使用了相對於$CATALINA_BASE的相對路徑,它和$CATALINA_HOME小有區別,如果只有一個tomcat實例,則它們是等價的,都是tomcat的安裝路徑。如果有多個tomcat實例,則$CATALINA_HOME表示的是安裝路徑,而$CATALINA_BASE表示的是各實例所在根目錄。關於tomcat多實例,見running.txt中對應的說明。
4.1 頂級元素server
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組件。
4.2 頂級元素service
定義了service就能提供服務了。service組件中封裝connector和containor,它同時也表示將此service中的connector和containor綁定起來,即由它們組成一個service向外提供服務。預設定義如下:
<Service name="Catalina">
</Service>
Service相關的屬性:
className
:用於實現service的類名,這個類必須實現org.apache.catalina.Service介面。不給定該屬性時將採用預設的標準類org.apache.catalina.core.StandardService。name
:此service的顯示名稱,該名稱主要用於在日誌中進行標識service。一般來說無關緊要,預設為Catalina。
4.3 執行器executor
執行器定義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" />
4.4 連接器connector
連接器用於接收客戶端發送的請求並返迴響應給客戶端。一個service中可以有多個connector。有多種connector,常見的為http/1.1,http/2和ajp(apache jserv protocol)。在tomcat中,ajp連接協議類型專用於tomcat前端是apache反向代理的情況下。
因此tomcat可以扮演兩種角色:
- Tomcat僅作為應用程式伺服器:請求來自於前端的web伺服器,這可能是Apache, IIS, Nginx等;
- Tomcat既作為web伺服器,也作為應用程式伺服器:請求來自於瀏覽器。
Tomcat應該考慮工作情形併為相應情形下的請求分別定義好需要的連接器才能正確接收來自於客戶端的請求。
此處暫先介紹HTTP/1.1連接器的屬性設置。ajp後文再做介紹。
HTTP連接器表示支持HTTP/1.1協議的組件。設置了該連接器就表示catalina啟用它的獨立web服務功能,當然,肯定也提供它必須的servlets和jsp執行功能。在一個service中可以配置一個或多個連接器,每個連接器都可以將請求轉發給它們相關聯的engine以處理請求、創建響應。
如果想要配置某個web server的連接器,則使用AJP協議。
每個流入的請求都需要一個獨立的線程來接收。當併發請求數量超出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" />
4.5 容器類engine
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實例上。
註意,jvmRoute同樣可以使用jvmRoute的系統屬性來設置。如果此處設置了jvmRoute,則覆蓋jvmRoute系統屬性。關於jvmRoute的使用,在後面tomcat ajp負載均衡的文章中介紹。
engine是容器中的頂級子容器,其內可以嵌套一個或多個Host作為虛擬主機,且至少一個host要和engine中的預設虛擬主機名稱對應。除了host,還可以嵌套releam和valve組件。
4.6 容器類host
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和webBase屬性即可,其餘採用預設,預設時會自動部署webapp。有時候還需要管理多個站點名稱,即主機別名。可以使用Alias為Host指定的主機名定義主機別名。如:
<Host name="web.a.com" appBase="webapps" unpackWARs="true">
<Alias>www.a.com</Alias>
</Host>
自動部署指的是自動裝載webapp以提供相關webapp的服務。
4.7 容器類context
connector和containor是整個tomcat的心臟,而context則是containor的心臟,更是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也是由此推斷出來的。規則如下:
- 如果path不為空,則context name等於context path,basefile name取path中去除首碼"/"後的路徑,且所有"/"替換為"#"。
- 如果path為空,則context name也為空,而basefile為ROOT(註意是大寫)。
例如:
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可以提升性能。
4.8 被嵌套類realm
realm定義的是一個安全上下文,就像是以哪種方式存儲認證時的用戶和組相關的資料庫。有多種方式可以實現數據存放:
- JAASRealm:基於Java Authintication and Authorization Service實現用戶認證;
- JDBCRealm:通過JDBC訪問某關係型資料庫表實現用戶認證;
- JNDIRealm:基於JNDI使用目錄服務實現認證信息的獲取;
- MemoryRealm:查找tomcat-user.xml文件實現用戶信息的獲取;
- UserDatabaseRealm:基於UserDatabase文件(通常是tomcat-user.xml)實現用戶認證,它實現是一個完全可更新和持久有效的MemoryRealm,因此能夠跟標準的MemoryRealm相容;它通過JNDI實現;
下麵是一個常見的使用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" />
4.9 被嵌套類valve
Valve中文意思是閥門,類似於過濾器,它可以工作於Engine和Host/Context之間、Host和Context之間以及Context和Web應用程式的某資源之間。一個容器內可以建立多個Valve,而且Valve定義的次序也決定了它們生效的次序。
有多種不同的Valve:
- AccessLogValve:訪問日誌Valve;
- ExtendedAccessValve:擴展功能的訪問日誌Valve;
- JDBCAccessLogValve:通過JDBC將訪問日誌信息發送到資料庫中;
- RequestDumperValve:請求轉儲Valve;
- RemoteAddrValve:基於遠程地址的訪問控制;
- RemoteHostValve:基於遠程主機名稱的訪問控制;
- SemaphoreValve:用於控制Tomcat主機上任何容器上的併發訪問數量;
- JvmRouteBinderValve:在配置多個Tomcat為以Apache通過mod_proxy或mod_jk作為前端的集群架構中,當期望停止某節點時,可以通過此Valve將用記請求定向至備用節點;使用此Valve,必須使用JvmRouteSessionIDBinderListener;
- ReplicationValve:專用於Tomcat集群架構中,可以在某個請求的session信息發生更改時觸發session數據在各節點間進行複製;
- SingleSignOn:將兩個或多個需要對用戶進行認證webapp在認證用戶時連接在一起,即一次認證即可訪問所有連接在一起的webapp;
- ClusterSingleSingOn:對SingleSignOn的擴展,專用於Tomcat集群當中,需要結合ClusterSingleSignOnListener進行工作;
其中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>
其中相關屬性定義有:
- className:在對應位置的尾碼上加上".valves.RemoteHostValve"或".valves.RemoteAddrValve";
- allow:以逗號分開的允許訪