天天看點

Tomcat源碼分析----Connector初始化與加載系列文章直達:

一個應用伺服器的性能很大程度上取決于網絡通信子產品的實作,是以Connector對于tomcat而言是重中之重。在本章節中以下兩個問題會被回答:

一個http請求是怎麼被tomcat監聽到的,會有哪些處理;

為什麼請求可以有需要通過nginx的,也可以不需要nginx的直接請求到tomcat上?

通過對Container的初始化分析,我們很自然的會回過頭看conf/server.xml中的connector配置。在xml中配置了2個connector。

為什麼會有多個Connector呢?我們部署伺服器的時候,通常會有2種方式:

1 直接部署tomcat,在浏覽器中請求http與tomcat直連

2 部署一個nginx作反向代理,tomcat與nginx直連

這就是上面兩種配置,通過協定protocol來區分。是以多個connector的好處是通過不同的協定,是tomcat伺服器能夠随着http的應用場景,伺服器架構的更新而相容起來。

好的,現在配置了2個Connector,那麼繼續思考一下,Connector是通信過程,如果是你你會怎麼設計?顯然需要做3件事:

(1)監聽端口,建立服務端與用戶端的連結;

(2)擷取到用戶端請求的socket資料,并對Socket資料進行解析和包裝成Http請求資料格式;

(3)将包裝後的資料交給Container處理。

通過源碼來分析,Connector有兩個屬性:protocolHandler(協定)和adapter(擴充卡),其中protocolHandler完成的是步驟(1)(2),adapter完成的是步驟(3)。

在Connector的構造方法中,通過反射生成protocolHandler.

協定的設定在conf/server.xml中配置,由setProtocol來指派,Tomcat提供了6種協定:

三種不帶Ajp的協定,用戶端與Tomcat伺服器直接連接配接。

Http11Protocol---------------預設協定,阻塞IO方式的支援http1.1協定

Http11NioProtocol----------非阻塞IO方式的支援http1.1協定

Http11AprProtocol----------使用ARP技術的支援http1.1協定(ARP:Apache portable runtime)

三種帶Ajp的協定為定向包協定,即WEB伺服器通過 TCP連接配接和SERVLET容器連接配接,例如tomcat和Apache、Nginx等前端伺服器連接配接

AjpProtocol--------------------阻塞IO方式的支援Ajp協定

AjpNioProtocol---------------非阻塞IO方式的支援Ajp協定

AjpAprProtocol---------------使用ARP技術的支援Ajp協定

為了便于分析,之對Http11Protocol進行分析,其他的大同小異。在Http11Protocol的構造方法中,對成員變量endpoint和cHandler進行初始化,這兩個很重要,後續會繼續講到。

繼續到Connector代碼中,由前面提到的tomcat啟動過程知道,會調用Connector兩個方法init和start。而端口的綁定和監聽則分别在這兩個方法中完成

調用的是initInternal,做了三件事:

1 擴充卡初始化成CoyoteAdapter;

2 調用Http11Protocol的init方法;

3 調用mapperListener的init方法。

步驟2中Http11Protocol的init方法,最終會調用到其父類AbstractProtocol的init方法,在這個方法裡面對endpoint(Http11Protocol使用的是JIoEndPoint)進行了初始化。

endpoint.init()在AbstractEndpoint中,完成了對需要監聽的端口的綁定。

在JIoEndpoint的bind()中完成了對端口的綁定。

Connector的啟動會調用start方法,在startInternal方法中,

其中,protocolHandler.start();即調用了Http11Protocol的start方法。最終調用了調用了JIoEndpoint的startInternal方法,初始化了連接配接請求處理的線程池,監聽端口的線程(預設200個)

OK,到了現在Connector的啟動已經透明化了,Connector的初始化工作其實是根據server.xml的配置,建立了服務端Socket來監聽用戶端的請求。并初始化了一個線程池來處理接收到的請求。

通過上面的分析,我們可以看到JIoEndpoint是一個阻塞式的IO模型;而若使用Http11NioProtocol協定,則調用的是NioEndpoint,是一個多路複用IO模型。