Tomcat的結構和對請求的處理
1. 問題
起因是裝開發環境。
工程是javaEE的,基於maven管理依賴,開發工具是eclipse和tomcat。
工程怎麼搞都啓動出錯,最後發現是該工程的web.xml中定義了自己的defaultservlet和jspservlet。
而tomcat啓動的時候,會首先讀取conf/web.xml下的定義,兩者之間肯定要有一個被comment掉。
tomcat玩了這麼多年,有必要把東西理一遍。
2. Tomcat的大結構
tomcat啓動之後,將作爲一個運行於JVM上的進程存在。
tomcat從層次上,最外圍是server本身。
然後server裏可以有多個service。每個service可以監聽幾個不同的端口號。
接下來,每個service裏有多個connector。不同的connector監聽不同的端口好,使用不同的通信協議。多個connector連接同一個container,container管轄多個webapp。
所有的這一切都定義在server.xml中。
- <!—最高節點 8005端口是shudown shell用端口號-->
- <Server port="8005" shutdown="SHUTDOWN">
- //JNDI全局資源
- <GlobalNamingResources>
- //service,可以有多個
- <Service name="Catalina">
- //connector 我們一般都是用8080端口的http請求
- <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- //每個connector都可以定義自己的線程池
- <Connector executor="tomcatThreadPool"
- port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- //處理請求的容器
- <Engine defaultHost="localhost" name="Catalina">
- //cluster配置
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- //虛擬主機,可以定義多個虛擬主機。比如www.aaa.com,www.bbb.com,全部映射到同一個容器中。(用於實現SSO)
- <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
- //具體的context,用來指明webapp的路徑
- <Context docBase="xxx" path="/xxx" reloadable="true" source="xxx"/>
作爲tomcat的啓動而言,一般來說
① 根據conf/server.xml啓動所有必要組建
② 加載conf/web.xml中所有配置
③ 依次加載所有webapp中的web.xml
3. Tomcat中請求的處理
假設來自客戶的請求爲:http://www.xxx.com/test/index.jsp
a. 請求被髮送到該物理機器的默認端口80,被在那裏偵聽的Coyote HTTP/1.1 Connector獲得 (沒有考慮apache)
b. Connector封裝http請求,並且從線程池中喚醒一個線程,將任務調度給該線程
- 被喚醒線程在Engine中尋找www.xxx.com匹配的虛擬主機
- 被找到的Host獲得請求/test/index.jsp,匹配它所擁有的所有Context
- Host匹配到路徑爲/test的Context(如果匹配不到就把該請求交給路徑名爲""的Context去處理)
- path="/test"的Context獲得請求/index.jsp
- Context開始解析http請求,首先由filter處理,再次交給servlet
現行的Web框架都是由filter攔截
順便提一下,這也就是爲什麼很多人說servlet不是線程安全的。
- Context把執行完了之後的HttpServletResponse對象返回給Host
- Host把HttpServletResponse對象返回給Engine
- Engine把HttpServletResponse對象返回給Connector
- Connector把HttpServletResponse對象返回給客戶browser
- 線程重回wait狀態