Tomcat Web應用程序部署
|
實踐
首先理解分析一下Tomcat的核心配置文件
Tomcat服務器是由一系列可配置的組件構成,其中核心組件是Catalina Servlet容器,它是所有其他Tomcat組件的頂層容器。Tomcat的組件可以在<CATALINA_HOME>/conf/server.xml文件中進行配置,每個Tomcat組件在server.xml文件中對應一種配置元素。以下代碼呈現了各種Tomcat組件之間的關系:
<Server>
<Service>
<Connector/>
<Engine>
<Host>
<Context>
</Context>
</Host>
</Engine>
</Service>
</Server>
以上XML代碼中,每個元素都代表一種Tomcat組件。
這些元素可分為四類。
1、 頂層元素類<Server>\<Service>
a) Server元素類
i. <Server>元素代表整個Catalina Servlet容器,因此它在conf/server.xml文件中必須是單獨的最外層元素,它的屬性表示整個Servlet容器的特征。<Server>元素中可包含一個或多個<Service>元素和GlobalNamingResources元素。
b) Service元素類
i. 一個Service元素表示一個或者多個Connector元素組件的組合,這些Connector元素組件共享一個單獨的Engine組件用於處理客戶端到來的請求。可以有一個或多個Service元素。
2、 連接器元素類<Connector>
連接器元素類代表了介於客戶與服務器之間的通信接口,負責將客戶的請求發送個服務器,並將服務器的響應結果傳遞給客戶。
a) Http Connector
i. Http Connector元素表示一個支持HTTP/1.1協議的Connector組件.它除了他的執行Servlet和JSP頁面的能力之外它使Catalina的功能能夠成為一個獨立的Web服務器。這個組件的一個實例在服務器的一個特定的TCP端口號上監聽客戶端到來的連接。一個或多個這樣的Connector能被配置為單個Service的部件,附送到管理的Engine去執行請求處理和創建響應。
b) AJP Connector
AJP Connector元素表示一個Connector組件,它通過這個AJP協議與一個Web Connector進行通信。這被用於你希望去整合Tomcat到一個存在的或新的Apache安裝的情形。並且你希望Apache去處理Web項目包含的靜態內容,並且或者利用Apache的SSL處理。
3、 容器元素類
容器元素類代表處理客戶請求並生成響應的結果的組件,有3種容器類型元素,他們是Engine、Host和Context。
3.1、Engine組件為特定的Service組件處理所有客戶請求,每個<Service>元素只能包含一個<Engine>元素。<Engine>元素處理在同一個<Service>中所有<Connector>元素接收到的客戶請求。並且返回完整的響應給Connector作為最終的傳輸返回給客戶端。
3.2、Host組件為特定的虛擬主機處理所有客戶請求,一個<Engine>元素中可以包含多個<Host>元素。每個<Host>元素定義了一個虛擬主機,它可以包含一個或多個Web應用。虛擬主機通常是一個網絡名的關聯,客戶端使用虛擬主機的網絡名可以連接到一個Tomato服務器。這個網絡名必須在DNS服務器注冊。
在許多情況下,系統管理員希望關聯多於一個網絡名到相同的虛擬主機和應用程序,這個可以通過使用主機別名<Alias>來完成。
一個或者多個Host元素被嵌套在一個Engine元素,在這個Host元素里面,對於與這個虛擬主機關聯的web應用程序你能嵌套Context元素在它里面。與某個Engine關聯的這些虛擬主機中的某一個必須有一個名字匹配Engine元素的defaultHost屬性。
客戶端通常使用主機名來標識它希望連接的服務器。這個主機名也被包含在HTTP請求頭。Tomcat從HTTP請求頭提取這個主機名並且使用一個匹配名字查詢一個Host。如果沒有匹配被發現,這個請求被路由到缺省主機。
3.3、Context組件為特定的Web應用處理所有客戶請求。<Context>元素是使用最頻繁的元素。每個<Context>元素代表了運行在虛擬主機上的單個Web應用程序,它運行在一個實際的虛擬主機內,每個Web應用程序是基於一個Web應用程序檔案文件或者一個相應目錄包含相應的解包內容。
Web應用程序處理每個HTTP請求的選擇方式是基於請求URI的最長可能前綴匹配原則,一旦被選擇,Context將依照servlet mapping的定義來選擇一個合適的Servlet來處理到來的請求。
你可以定義多個Context元素,如果你需要的話。每個Context必須擁有一個唯一的Context名字。
一個<Host>元素中可以包含多個<Context>元素。
4、 嵌套類元素
嵌套類元素代表了可以加入到容器中的組件,如<Logger>元素、<Valve>元素和<Realm>元素。
Tomcat中各個組件之間的關系:
一個Server可以包含一個到多個Service,
一個Service看一個包含多個連接器Connector和一個Engine,
多個連接器共享一個Engine
同一個Engine中可以有多個Host.
同一個Host中包含多個Context。
下面看一個具體的案例:
現有兩個應用客戶端訪問地址分別為:
Http://localhost:8080/app1/index.jsp
Http://localhost:8080/app2/index.jsp
處理步驟說明:
1、 請求被8080端口監聽的Connector1接收到
2、 Connector1把請求交給共享的Engine處理
3、 Engine根據HTTP請求頭里面的主機頭Host決定該交給那個虛擬主機處理,很明顯這里主機頭是locahost,因此交給locahost這個虛擬主機處理
4、 虛擬主機根據Context決定請求交給哪個應用程序上下文處理,這里客戶端1發出的請求將交給app1處理。
示范:
靜態部署這里不示范,這里示范動態部署。
一、通過拷貝到webapps目錄來實現動態部署
我的d盤根目錄有一Web應用程序app1:
先將其直接拷貝到webapps目錄下:
觀察Tomcat的日志輸出:
如下:
信息: Deploying web application directory E:\WorkSpace\JavaWorkspace\Tomcat 7.0\webapps\app1
2012-6-3 23:18:31 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Parsing configuration file [struts-default.xml]
2012-6-3 23:18:31 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Parsing configuration file [struts-plugin.xml]
2012-6-3 23:18:31 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Parsing configuration file [struts.xml]
說明拷貝進去的項目被自動部署了。
我們再次刪除這個項目,但是提示:
這個是因為應用中的jar包被鎖定的緣故,查看tomcat的Context屬性,如下:
http://localhost:8080/docs/config/context.html
antiJARLocking |
If true, the Tomcat classloader will take extra measures to avoid JAR file locking when resources are accessed inside JARs through URLs. This will impact startup time of applications, but could prove to be useful on platforms or configurations where file locking can occur. If not specified, the default value isfalse. antiJARLocking is a subset ofantiResourceLocking and therefore, to prevent duplicate work and possible issues, only one of these attributes should be set totrue at any one time. |
我們修改conf/ context.xml,添加屬性antiResourceLocking=true,如下:
<Context antiResourceLocking="true">
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
再次刪除app1,就不會有上面的提示了。刪除app1后我們觀察日志輸出:
信息: Undeploying context [/app1]
2012-6-3 23:27:02 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
嚴重: The web application [/app1] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@3ca56f]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@191394e]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
2012-6-3 23:27:02 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
嚴重: The web application [/app1] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@3ca56f]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@149494e]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
2012-6-3 23:27:02 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
嚴重: The web application [/app1] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@3ca56f]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@6bbb36]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
2012-6-3 23:27:02 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
嚴重: The web application [/app1] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@3ca56f]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@d006a7]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
二、通過為Web應用程序添加一個特定的Context文件來實現動態部署
我們找到以下位置:conf/Catalina/localhost,這個目錄代表什么?
Catalina代表server.xml文件里面配置的默認的Service的名稱。
Localhost代表Service里面的默認虛擬主機名稱。
我們現在就是要在這個虛擬主機里面部署我們的應用。
做法:
1、 創建一個xml文件,文件名和Web應用名相同:app1.xml。
2、 這個文件的內容如下:
a) <Context path="/app1" docBase="d:/app1" debug="0" privileged="true" workDir="d:/app1work"></Context>
3、 將這個文件拷貝到conf/Catalina/localhost下面,完整路徑就是conf/Catalina/localhost/app1.xml,這時Tomcat會自動掃描到這個文件然后根據里面的描述加載應用上下文的。
4、 觀察現在的日志輸出:
l 信息: Deploying configuration descriptor E:\WorkSpace\JavaWorkspace\Tomcat 7.0\conf\Catalina\localhost\app1.xml
l 2012-6-3 23:41:23 org.apache.catalina.startup.SetContextPropertiesRule begin
l 警告: [SetContextPropertiesRule]{Context} Setting property 'debug' to '0' did not find a matching property.
l 2012-6-3 23:41:24 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
l 信息: Parsing configuration file [struts-default.xml]
l 2012-6-3 23:41:24 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
l 信息: Parsing configuration file [struts-plugin.xml]
l 2012-6-3 23:41:24 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
l 信息: Parsing configuration file [struts.xml]
5、 刪除這個文件后,日志輸出:
l 信息: Undeploying context [/app1]
l 2012-6-3 23:43:06 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
l 嚴重: The web application [/app1] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@1f1a3a8]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@12f9ee1]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.