tomcat配置文件目錄是conf目錄,主要配置文件有5個,下面一個個分析下。
1.context.xml
Context.xml是Tomcat公用的環境配置,tomcat服務器會定時去掃描這個文件。一旦發現文件被修改(時間戳改變了),就會自動重新加載這個文件,而不需要重啓服務器。不同於server.xml 文件是不可動態重加載的資源,服務器一旦啓動了以後,要修改這個文件,就得重啓服務器才能重新加載。
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
//監聽web.xml文件,文件變動後重新加載
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
2.web.xml
我們web應用的默認配置文件。比如:
默認Servlet
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
默認JSPServlet
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
Servlet可以處理的請求
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
可以處理的請求類型,只要只貼出部分我們常見的請求類型
json application/json jsonml application/jsonml+json jspf text/plain3.tomcat-users.xml
這個是tomcat自動的應用管理工具Tomcat Manager訪問的用戶權限配置。
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
tomcat內部的分爲哪幾個角色,每個角色可以訪問什麼資源,這些在哪裏看?
在tomcat目錄下的webapps\manager\WEB-INF目錄下面的web.xml文件。這個就是tomcat自動管理應用的web.xml文件。
其中有security-role節點,定義了有哪些角色
<security-role>
<description>
The role that is required to access the HTML Manager pages
</description>
<role-name>manager-gui</role-name>
</security-role>
<security-role>
<description>
The role that is required to access the text Manager pages
</description>
<role-name>manager-script</role-name>
</security-role>
<security-role>
<description>
The role that is required to access the HTML JMX Proxy
</description>
<role-name>manager-jmx</role-name>
</security-role>
<security-role>
<description>
The role that is required to access to the Manager Status pages
</description>
<role-name>manager-status</role-name>
</security-role>
還有個security-constraint節點定義了每個角色可以訪問什麼資源
<security-constraint>
<web-resource-collection>
<web-resource-name>HTML Manager interface (for humans)</web-resource-name>
<url-pattern>/html/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-gui</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Text Manager interface (for scripts)</web-resource-name>
<url-pattern>/text/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-script</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>JMX Proxy interface</web-resource-name>
<url-pattern>/jmxproxy/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-jmx</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Status interface</web-resource-name>
<url-pattern>/status/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-gui</role-name>
<role-name>manager-script</role-name>
<role-name>manager-jmx</role-name>
<role-name>manager-status</role-name>
</auth-constraint>
</security-constraint>
4.jaspic-providers.xml
這個配置文件集成第三方JASPIC身份驗證,我們不常用,這裏不分析。
5.server.xml
server.xml是tomcat的核心配置文件。先大致看一眼,再分析。
<?xml version="1.0" encoding="UTF-8"?>
//server是頂層元素,只能有一個
<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將Connector和Engine包裝起來,統一對外提供服務。一個server可以有不同的service
//不同的service監聽不同的端口
<Service name="Catalina">
//線程池
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4" />
//Connector監聽端口爲8080,處理協議HTTP1.1協議
//創建Request和Response對象,然後分配線程讓Engine來處理這個請求
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
//處理Connector發送的請求,並把相應返回給Connector
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" />
</Realm>
//虛擬節點,處理對應域名或者ip的請求
<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>
5.1 server元素
整個配置文件的根元素,代表整個tomcat容器,一個tomcat中只能有一個server元素。Server的作用就是提供一個接口,讓客戶端能夠訪問內部Service集合,同時維護所有的Service的生命週期,包括初始化、結束服務以及如何找到客戶端要訪問的Service。
屬性:
- className:server元素對應的處理類,默認是StandardServer。tomcat的server實現類必須實現org.apache.catalina.Server接口
- Port:Tomcat將在這個接口監聽關閉服務器的命令
- Shutdown:關閉Tomcat服務器的命令字符串
5.2 Listener元素
Listener就是監聽器,監聽特定事件發生並執行特定的操作。監聽器可以在Server、Engine、Host或Context中。
屬性:
- className:監聽器的具體實現類,監聽器必須實現org.apache.catalina.LifecycleListener接口。
介紹幾個常用監聽器:
- VersionLoggerListener:Tomcat啓動時,記錄Tomcat、Java和操作系統的信息,必須配置在第一個
- AprLifecycleListener:Tomcat啓動時,檢查APR庫,如果存在則加載
- JasperListener:Web應用啓動之前初始化Jasper。Jasper是JSP引擎,把JSP文件解析成java文件,然後編譯成class文件供JVM使用
- JreMemoryLeakPreventionListener:與類加載器導致的內存泄露有關。
- GlobalResourcesLifecycleListener:通過該監聽器,初始化GlobalNamingResources標籤中定義的全局JNDI資源
- ThreadLocalLeakPreventionListener:當Web應用因ThreadLocal導致的內存泄露而要停止時,該監聽器會觸發線程池中線程的更新。只有當Context元素的renewThreadsWhenStoppingContext屬性設置爲true時,該監聽器纔有效
5.3 Service元素
service就是將其內部的Connector和Engine包裝起來,統一對外提供服務。一個Service可以包含多個Connector,但是隻能包含一個Engine。其中Connector的作用是從客戶端接收請求,然後轉交給Engine處理,Engine處理完成後將響應返回給Connector,Connector再返回給客戶端。
5.4 Connector元素
Connector就是連接器。作用是接收客戶端的連接請求,創建Request和Response對象,然後分配線程讓Engine來處理,並把產生的Request和Response對象傳給Engine。Engine處理完後將Response返回給Connector,Connector再返回給客戶端。
屬性:
- allowTrace:是否允許HTTP的TRACE方法,默認爲false
- enableLookups:如果爲true,調用request.getRemoteHost()遠程主機的主機名。如果爲false,則直接返回IP地址
- maxPostSize:POST請求的最大數量,沒有指定默認爲2097152
- protocol:請求協議,比如HTTP1.1,或者AJP/1.3
- redirectPort:重定向端口,比如連機器不支持SSL,請請求轉發給這個端口
- secure:SSL連接器中設置爲true,默認爲false;
- URIEncoding:URL編碼,默認爲ISO-8859-1;
- acceptCount:當accept隊列中連接的個數達到acceptCount時,後續請求一律被拒絕。默認值是100
- bufferSize:輸入流緩衝區大小,默認2048字節;
- compressableMimeType:MIME的列表,默認是text/html,text/xml,text/plain;
- compression:是否對響應數據壓縮。off是禁止壓縮,on是允許壓縮。force是所有情況下都進行壓縮,默認不壓縮
- connectionTimeout:連接超時時間
- maxHttpHeaderSize:HTTP請求和響應頭的最大量,默認爲4096字節;
- maxKeepAliveRequest:長連接最大數
- port:監聽的端口
- maxConnections:Tomcat在任意時刻接收和處理的最大連接數
(1)一個Service可以包含多個Connector,比如```
//處理以http協議訪問8080端口的請求,當要求請求是https,但請求是http時,重定向到端口號爲8443的Connector
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
//處理以AJP協議訪問8009端口的請求。AJP協議負責和其他的HTTP服務器(如Apache)建立連接。
//Tomcat常用來作爲Servlet/JSP容器,但是對靜態資源的處理速度較慢,不如Apache等HTTP服務器,所以有時會將Tomcat和Apache集成,這時候就會用到這個連接器。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
(2)Connector重要參數詳細說明
Connector是處理客戶端連接請求的,分配線程讓Engine處理,所以Connector參數的配置直接影響tomcat的性能,這裏詳細說明下幾個重要的參數。
Connector處理請求分爲BIO和NIO兩種方式。
BiO的處理流程:
客戶端通過TCP三次握手和服務器建立連接後,連接請求socket會放入一個accept隊列。Connector中主要通過JIoEndpoint對象處理請求,JIoEndpoint對象維護了Acceptor和Worker。Acceptor負責從accept隊列接收socket,然後從Worker線程池中找出空閒的線程處理socket。如果沒有空閒線程,Acceptor將阻塞。其中如果配置了Executor,使用的是Worker線程池就是Executor,否則是tomcat自帶的線程池。
NiO的處理流程:
客戶端通過TCP三次握手和服務器建立連接後,連接請求socket會放入一個accept隊列。Connector中主要通過NIoEndpoint對象處理請求,NIoEndpoint對象維護了Acceptor、Worker和Poller。Acceptor負責從accept隊列接收socket,然後Acceptor將請求放入了一個隊列,Poller從隊列中消費請求,並將該請求註冊到一個Selector選擇器,然後輪詢Selector找到真正有請求數據的,再從Worker線程池中找出空閒的線程處理socket。如果沒有空閒線程則將阻塞。其中如果配置了Executor,使用的是Worker線程池就是Executor,否則是tomcat自帶的線程池。
目前大多數HTTP請求使用的是長連接,也就是說socket在當前請求結束後,socket不會立馬釋放,而是等timeout後再釋放,相應的線程會一直被佔用。使用BIO,有socket連接後直接交給線程處理,不管有沒有讀寫請求,所以Tomcat同時處理的socket數目不能超過最大線程數,性能受到限制。而使用NIO,socket是註冊到Selector選擇器,有讀寫請求後才交給線程處理,所以Tomcat可以同時處理的socket數目可以遠大於最大線程數,併發性能大大提高。
acceptCount、maxConnections、maxThreads參數
- acceptCount
accept隊列的長度;當accept隊列中連接的個數達到acceptCount時,隊列滿,進來的請求一律被拒絕。默認值是100。 - maxConnections
Tomcat在任意時刻接收和處理的最大連接數。當Tomcat接收的連接數達到maxConnections時,Acceptor線程不會讀取accept隊列中的連接。這時accept隊列中的線程會一直阻塞着,直到Tomcat接收的連接數小於maxConnections。如果設置爲-1,則連接數不受限制。
NIO的默認值是10000,APR/native的默認值是8192,而BIO的默認值爲maxThreads(如果配置了Executor,則默認值是Executor的maxThreads)。 - maxThreads
處理請求線程的最大數量。默認值是200。如果該Connector綁定了Executor,這個值會被忽略,因爲該Connector將使用綁定的Executor,而不是內置的線程池來執行任務。
Executor的主要屬性包括
- name:該線程池的標記
- maxThreads:線程池中最大活躍線程數,默認值200(Tomcat7和8都是)
- minSpareThreads:線程池中保持的最小線程數,最小值是25
- maxIdleTime:線程空閒的最大時間,當空閒超過該值時關閉線程(除非線程數小於minSpareThreads),單位是ms,默認值60000(1分鐘)
- daemon:是否後臺線程,默認值true
- threadPriority:線程優先級,默認值5
- namePrefix:線程名字的前綴,線程池中線程名字爲:namePrefix+線程編號
5.5 Engine元素
Engine在Service中只能由一個;Engine是Service組件中的請求處理組件。Engine組件從一個或多個Connector中接收請求並處理,並將完成的響應返回給Connector。
Engine、Host和Context都是容器,Engine包含Host,Host包含Context。Engine中至少有一個Host元素,並且必須有一個Host屬性的名字與defaultHost指定的名字相匹配。
屬性:
- className:Engine元素的實現類,默認是StandardEngine。實現類必須實現org.apache.catalina.Engine接口
- defaultHost:默認主機名,值必須與Service的name值相匹配
- name:Engine名稱
- jvmRoute:在負載勻衡中使用的標識符
5.6 Host元素
Host表示一個虛擬主機。
屬性:
- appBase:設定應用程序的基目錄,絕對路徑或相對於%CATALINA_HOME%的路徑名
- autoDeploy:指示Tomcat運行時,如有新的WEB程序在appBase指定的目錄下,是否自動佈署,默認值爲true
- className:Host元素實現類名,默認是StandardHost。Host實現類必須實現org.apache.catalina.Host接口
- deployOnStartup:Tomcat啓動時,是否自動部署appBase屬性指定目錄下所有的WEB應用程序,默認值爲true
- name:虛擬主機名稱
- deployXML:爲false將不會解析WEB應用程序內部的context.xml,默認值爲true;
- unPackWARs:是否將Web應用的WAR文件解壓
autoDeploy和deployOnStartup區別
- deployOnStartup爲true時,Tomcat在啓動時檢查Web應用,檢測到的所有Web應用都是新應用
- autoDeploy爲true時,Tomcat在運行時定期檢查是否有新的Web應用或Web應用的更新
應用的新增或者更新的檢查目錄爲Host元素的appBase和xmlBase配置。appBase屬性指定Web應用所在的目錄,默認值是webapps。xmlBase屬性指定Web應用的XML配置文件所在的目錄,默認值爲conf/<engine_name>/<host_name>。
5.7 Context元素
Context代表在特定虛擬主機上運行的一個WEB應用程序,需處理當前WEB應用程序的所有請求,每一個ontext必須使用唯一的上下文路徑。
Context是Host的子容器,每個Host中可以定義任意多的Context元素。
屬性:
- className:Context元素實現類,默認是StandardContext。Context實現類必須實現org.apache.catalina.Context接口
- cookies:是否將Cookie應用於Session,默認值爲true
- crossContext:是否允許跨域訪問
- docBase:絕對路徑或相對於Host的appBase 屬性的相對路徑,代表WAR包路徑或者應用目錄,注意docBase在appBase目錄時,不需要指定
- privileged:是否允許Web應用程序使用容器的Servlet
- path:訪問該Web應用的上下文路徑。一個虛擬主機中,上下文路徑必須唯一
- reloadable:Tomcat運行時,如果WEB-INF/classes和WEB-INF/lib目錄中有改變,否自動重新加載。對性能影響比較大,慎用
- cacheMaxSize:靜態資源緩存最大值,以KB爲單位,默認值爲10240KB;
- cachingAllowed:是否允許靜態資源緩存,默認爲true
- caseSensitive:資源文件名大小寫是否敏感
- unpackWAR:是否解壓war包
- workDir:Servlet指定臨時讀寫的目錄
有時候我們的server.xml配置文件中並沒有Context元素。這是因爲Tomcat開啓了自動部署,這時候path屬性由配置文件(xmlBase目錄下xml文件)的文件名、WAR文件的文件名或應用目錄的名稱自動推導出來。如果名稱是ROOT,則該Web應用是虛擬主機默認的Web應用,此時path屬性推導爲""。
5.8 Valve元素
Valvee在Tomcat中代表了請求處理流水線上的一個組件,Valve可以與Tomcat的容器Engine、Host或Context關聯。不同的Valve有不同的特性,這裏介紹一下上面出現的AccessLogValve。
AccessLogValve的作用是通過日誌記錄其所在的容器中處理的所有請求,在上述文件中Valve放在Host下,可以記錄該Host處理的所有請求。
AccessLogValve的屬性
- className:Valve實現類
- directory:日誌存儲的目錄
- prefix:日誌文件的前綴
- suffix:日誌文件的後綴
- pattern:記錄日誌的格式,%h:遠程主機名或IP地址;%l:遠程邏輯用戶名,一般是”-”;%u:授權的遠程用戶名,如果沒有則是”-”;%t:訪問的時間;%r:請求的第一行,即請求方法(get/post等)、uri、及協議;%s:響應狀態,如404等等;%b:響應的數據量,不包括請求頭,如果爲0,則是”-”;%D,含義是請求處理的時間
6.總結
先看下tomcat的架構圖
tomcat中只能由一個server,一個server中可以包含多個service,一個service中只能包含一個Engine,可以包含多個Connector,一個Engine可以包含多個host,一個host中可以包含多個Context。
tomcat處理流程:
- 客戶端發起請求tomcat容器
- service找到符合端口和協議的Connector執行
- Connector創建Request和Response對象,創建線程,交給Engine執行
- 請求流轉到Engine後,會進入它的pipeline組件,並且經過內部Valve的過濾,然後Engine根據訪問的域名或者ip找到對應host執行
- 請求流轉到Host後,會進入它的pipeline組件中,並且經過內部Valve的過濾,然後host請求路徑找到對應的Context下的應用
- 請求流轉到Context後,會進入它的pipeline組件中,並且經過內部Valve的過濾,然後交給Wrapper執行
- 請求流轉到Wrapper後,會進入它的pipeline組件中,並且經過內部Valve的過濾,Wrapper內部的WrapperValve創建FilterChain實例,調用指定的Servlet實例處理請求
- 最後將請求結果返回