本篇結(jié)構(gòu):
- 前言
- 什么是Coyote
- Coyote支持的協(xié)議及I/O方案
- Coyote重要組件
- 總結(jié)
一、前言
Tomcat是一款servlet服務(wù)器,它能夠接受請求,處理請求并給出響應(yīng)。
前面的篇章介紹了Tomcat容器框架Catalina的相關(guān)內(nèi)容,主要介紹了Tomcat容器的初始化和啟動(dòng),并沒有介紹這些容器啟動(dòng)之后做什么,其實(shí)Catalina容器啟動(dòng)后主要是負(fù)責(zé)處理來自客服端的請求并輸出響應(yīng)。
之所以沒有在前面的篇幅介紹這些,是因?yàn)镃atalina容器只負(fù)責(zé)處理請求,而請求的接收是由Tomcat的連接器來做的,只有把Tomcat的Tomcat的連接器搞清楚了,才能完整理解Tomcat是怎樣處理Web請求的。
所以在正式介紹Tomcat是如何處理請求之前,先來了解下Tomcat的連接器。
二、什么是Coyote

如上,Coyote是Tomcat源碼中的一個(gè)包名,也可以說是Tomcat連接器框架的名字,是Tomcat服務(wù)器提供的供客戶端訪問的外部接口??蛻舳送ㄟ^Coyote與服務(wù)器建立連接、發(fā)送請求并接收響應(yīng)。
Coyote封裝了底層的網(wǎng)絡(luò)通信,為Catalina容器提供統(tǒng)一的接口,使得Catalina容器和具體的請求協(xié)議及I/O方式解耦。Coyote將Socket輸入轉(zhuǎn)換為自定義的Request對(duì)象,交由Catalina容器處理,處理完請求后,Catalina容器通過Coyote提供的自定義Response對(duì)象將結(jié)果寫入輸出流。
Coyote是相對(duì)獨(dú)立的模塊,和Servlet的規(guī)范實(shí)現(xiàn)沒有直接關(guān)系,它只負(fù)責(zé)網(wǎng)絡(luò)協(xié)議和I/O的處理,由它自定義的Request和Response對(duì)象也沒有實(shí)現(xiàn)Servlet規(guī)范對(duì)應(yīng)的接口,而是在Catalina容器中進(jìn)一步被封裝成ServletRequest和ServletResponse。
可以通過下圖簡單理解下:

三、Coyote支持的協(xié)議及I/O方案
3.1、Coyote支持的協(xié)議
在server.xml中可以看到這樣的配置:
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
...
<Service/>
這個(gè)配置是說一個(gè)Service可以配置多個(gè)Connector,支持不同的網(wǎng)絡(luò)協(xié)議。
由配置可知,Tomcat主要支持兩種協(xié)議:
- HTTP/1.1協(xié)議:這是大部分Web應(yīng)用采用的訪問協(xié)議,多用于Tomcat單獨(dú)運(yùn)行的情況。
- AJP協(xié)議:用于和Web服務(wù)器集成(如Apache HTTP Server),以實(shí)現(xiàn)針對(duì)靜態(tài)資源的優(yōu)化及集群部署。
3.2、Coyote I/O方案
Tomcat自8.5及9.0版本起,已經(jīng)移除了對(duì)BIO的支持,目前支持的I/O方案有:
- NIO:采用Java NIO類庫實(shí)現(xiàn)。
- NIO2:采用JDK 7最新的NIO2類庫實(shí)現(xiàn)。
- APR:采用APR(Apache可移植運(yùn)行庫)實(shí)現(xiàn),是使用C/C++編寫的本地庫,選擇該方案,需要單獨(dú)安裝APR庫。
四、Coyote重要組件
Coyote是Tomcat連接器框架的名稱,這節(jié)簡單介紹下Coyote涉及到的主要的組件,了解下這些組件的概念。
先看看在之前的篇章--整體架構(gòu)中貼出的一張連接器的設(shè)計(jì)結(jié)構(gòu)圖:

可以說Connector就是Tomcat的連接器,是Coyote最直接的體現(xiàn)。
4.1、ProtocolHandler
ProtocolHandler是Tomcat協(xié)議接口,Connector使用ProtocolHandler來處理請求。ProtocolHandler由包含了三個(gè)部件:Endpoint、Processor、Adapter。
它實(shí)現(xiàn)針對(duì)具體協(xié)議的處理功能。按照協(xié)議和I/O有如下繼承關(guān)系:

在server.xml中設(shè)置連接器時(shí),需要指定具體的ProtocolHandler,也可以制定協(xié)議的名稱,比如HTTP/1.1。
4.2、Endpoint
Endpoint是通信端點(diǎn),即通信監(jiān)聽的接口,是具體的Socket接收處理類,是對(duì)傳輸層的抽象。由于是處理底層的Socket網(wǎng)絡(luò)連接,因此Endpoint是用來實(shí)現(xiàn)TCP/IP協(xié)議的。
Tomcat并沒有Endpoint接口,而是一個(gè)抽象類AbstractEndpoint,根據(jù)I/O方式的不同,提供了如下的實(shí)現(xiàn):

Endpoint內(nèi)部有個(gè)Handler接口,用于處理接收到的Socket,在內(nèi)部調(diào)用Processor進(jìn)行處理。
Acceptor是Endpoint的一個(gè)部件,用于監(jiān)聽請求。
4.3、Processor
Processor是協(xié)議處理接口,負(fù)責(zé)構(gòu)造Request和Response對(duì)象,并通過Adapter將其提交到Catalina容器處理,是對(duì)應(yīng)用層協(xié)議的抽象。
在Coyote中,根據(jù)協(xié)議的不同有三個(gè)不同的實(shí)現(xiàn)類,另外還有兩個(gè)具體的升級(jí)協(xié)議處理的實(shí)現(xiàn)。
參見下圖:

4.4、Adapter
Adapter充當(dāng)適配器,將Processor構(gòu)造的Request對(duì)象轉(zhuǎn)換為ServletRequest交給Container進(jìn)行具體的處理。
只有一個(gè)實(shí)現(xiàn)類:CoyoteAdapter。
五、總結(jié)
下面就應(yīng)該介紹Connector是怎么初始化啟動(dòng)的,了解了這些就可以真正開始看Tomcat是如何處理請求的。