從聯結器元件看Tomcat的執行緒模型——聯結器簡介

程式設計師自由之路發表於2020-07-15

Connector元件介紹

Connector(聯結器)元件是Tomcat最核心的兩個元件之一,主要的職責是負責接收客戶端連線和客戶端請求的處理加工。每個Connector都將指定一個埠進行監聽,分別負責對請求報文解析和對響應報文組裝。

Connector元件是整個Tomcat的入口,假如我們想要學習Tomcat的原始碼的話,建議從Connector元件開始看起。

還有一個比喻就是Tomcat是一座城堡,而Connector元件就是這座城堡的一個個城門。

上圖是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協議通訊。

但是現在的主流開發模式中,都是使用前後端分離進行開發。比如說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模式。

相關文章