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 后默認采用該模式 |
|
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模式。