從聯結器元件看Tomcat的執行緒模型——聯結器簡介
阿新 • • 發佈:2020-07-15
## Connector元件介紹
Connector(聯結器)元件是Tomcat最核心的兩個元件之一,主要的職責是負責接收客戶端連線和客戶端請求的處理加工。每個Connector都將指定一個埠進行監聽,分別負責對請求報文解析和對響應報文組裝。
Connector元件是整個Tomcat的入口,假如我們想要學習Tomcat的原始碼的話,建議從Connector元件開始看起。
還有一個比喻就是Tomcat是一座城堡,而Connector元件就是這座城堡的一個個城門。
![](https://img2020.cnblogs.com/blog/1775037/202007/1775037-20200712170920125-805476710.png)
上圖是Connector元件的一個典型實現,其包含Protocol元件、Mapper元件和CoyoteAdaptor元件。
Protocol元件是協議的抽象,它將不同通訊協議的處理進行了封裝,比如**HTTP協議和AJP協議(目前Tomcat只支援這兩種協議)**。Endpoint是接收端的抽象,由於使用了不同的I/O模式,因此存在多種型別的Endpoint,如BIO模式的JIoEndpoint、NIO模式的NioEndpoint和本地庫I/O模式的AprEndpoint。Acceptor是專門用於接收客戶端連線的接收器元件,**Executor則是處理客戶端請求的執行緒池, Connector可能是使用了Service元件的共享執行緒池,也可能是Connector自己私有的執行緒池**。Processor元件是處理客戶端請求的處理器,不同的協議和不同的I/O模式都有不同的處理方式,所以存在不同型別的Processor。
Mapper元件可以稱為路由器,它提供了對客戶端請求URL的對映功能,即可以通過它將請求轉發到對應的Host元件、Context元件、Wrapper元件以進行處理並響應客戶端,也就是我們常說的**將某客戶端請求傳送到某虛擬主機上的某個Web應用的某個Servlet**。
CoyoteAdaptor元件是一個介面卡,它負責將Connector元件和Engine容器適配連線起來。把接收到的客戶端請求報文解析生成的請求物件和響應物件Response傳遞到Engine容器,交由容器處理。
## 聯結器支援的協議以及對應的IO模型
上面簡單提到Tomcat暫時支援HTTP和AJP兩種協議,對於每種協議又會有不同的IO模型,所以會有以下組合。
對於Http協議,Tomcat支援以下四種IO模型:
- Http11Protocol:傳統的BIO模型,對應的類為org.apache.coyote.http11.Http11Protocol
- Http11NioProtocol:NIO模式,對應的類為org.apache.coyote.http11.Http11NioProtocol
- Http11AprProtocol:Apr模式,對應的類為org.apache.coyote.http11.Http11AprProtocol
- Http11Nio2Protocol:AIO模式,對應的類是org.apache.coyote.http11.Http11Nio2Protocol
| | 描述 | 配置方法 server.xml |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| NIO | 同步非阻塞,比傳統BIO能更好的支援大併發,tomcat 8.0 後預設採用該模式 | 改為 protocol="org.apache.coyote.http11.Http11NioProtocol" |
| BIO | 阻塞式IO,tomcat7之前預設,採用傳統的java IO進行操作,該模式下每個請求都會建立一個執行緒,適用於併發量小的場景 | protocol =" org.apache.coyote.http11.Http11Protocol" |
| APR | tomcat 以JNI形式呼叫http伺服器的核心動態連結庫來處理檔案讀取或網路傳輸操作,需要編譯安裝APR庫(也就是說IO操作的部分直接呼叫native程式碼實現) | protocol ="org.apache.coyote.http11.Http11AprProtocol" |
| AIO | 非同步非阻塞 (NIO2),tomcat8.0後支援。多用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作,程式設計比較複雜 | protocol ="org.apache.coyote.http11.Http11Nio2Protocol" |
需要注意的是:上面四種IO模型的聯結器我們可以同時配置使用,只要他們監聽不同的埠就行了。
對於Ajp協議,Tomcat也支援下面幾種IO模型:
- AjpProtocol:對用傳統的BIO
- AjpNioProtocol:對應NIO
- AjpAprProtocol:對應Apr模式
- AjpNio2Protocol:對應AIO模式
這幾種模式和上面的模式只是協議上的區別,我們可以重點學習Http協議的實現,畢竟這是我們平時開發中更加常用的實現。
> 關於AJP協議這邊做下簡單的介紹。
>
> Tomcat最主要的功能是提供Servlet/JSP容器,儘管它也可以作為獨立的Java Web伺服器,它在對靜態資源(如HTML檔案或影象檔案)的處理速度,以及提供的Web伺服器管理功能方面都不如其他專業的HTTP伺服器,如IIS和Apache的伺服器。
>
> 因此在實際應用中,常常把Tomcat的與其他HTTP伺服器整合。對於不支援的Servlet/JSP的HTTP伺服器,可以通過的Tomcat伺服器來執行的Servlet/JSP元件,而對於靜態資源的處理還是在原來的Web伺服器中處理。
>
> Apache伺服器和Tomcat的連線通訊就可以通過AJP協議通訊。
>
> ![](http://sy0.img.it168.com/article/1/1257/1257835.jpg_i-730x550)
>
> 但是現在的主流開發模式中,都是使用前後端分離進行開發。比如說Nginx伺服器處理靜態資源,Tomcat處理動態請求,Nginx和和Tomcat中間通過ajax請求進行通訊,而ajax也是通過http協議進行通訊的。所以AJP協議在平時開發中用的較少。
在BIO模式下,對於每個客戶端的請求連線都將消耗執行緒池裡面的一條連線,直到整個請求響應完畢。此時,如果有很多請求幾乎同時到達Connector,當執行緒池中的空閒執行緒用完後,則會建立新的執行緒,直到達到執行緒池最大執行緒數。但如果此時還有更多請求到來,雖然執行緒池已經處理不過來,但作業系統還是會將客戶端接收起來放到一個佇列裡,這個佇列的大小通過SocketServer設定backlog而來。如果還是有再多的請求過來,佇列已經超過了SocketServer的backlog大小,那麼連線將直接被拒絕掉,客戶端將收到“connection refused”報錯。
在NIO模式下,則是所有客戶端的請求連線先由一個接收執行緒接收,然後由若干(一般為CPU個數)執行緒輪詢讀寫事件,最後將具體的讀寫操作交由執行緒池處理。可以看到,以這種方式,客戶端連線不會在整個請求響應過程佔用連線池內的連線,它可以同時處理比BIO模式多得多的客戶端連線數,此種模式能承受更大的併發,機器資源使用效率高很多。
APR/native模式也是NIO模式,只不過它是直接用原生代碼實現NIO模式(而不是基於JDK的NIO)。
AIO模式,使用JDK的AIO