從連接器組件看 Tomcat 的線程模型


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模式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM