天天看點

Tomcat是如何處理一次請求的 源碼版本8.0.21

目錄

​​1.Tomcat容器構成​​

​​2.Tomcat是如何接收一次請求的​​

1.Tomcat容器構成

Tomcat是如何處理一次請求的 源碼版本8.0.21

2.Tomcat是如何接收一次請求的

        從上圖可知Tomcat中有很多容器,包括Server、Service、Connector等。其中Connector正是與HTTP請求處理相關的容器。Connector的實作分為以下幾種:

  • Http Connector:基于HTTP協定,負責建立HTTP連接配接。它又分為BIO Http Connector與NIO Http Connector兩種,後者提供非阻塞IO與長連接配接Comet支援。
  • AJP Connector:基于AJP協定,AJP是專門設計用于Tomcat與HTTP伺服器通信定制的協定,能提供較高的通信速度和效率。如與Apache伺服器內建時,采用這個協定。
  • APR HTTP Connector:用C實作,通過JNI調用的。主要提升對靜态資源(如HTML、圖檔、CSS、JS等)的通路性能。

具體源碼實作:setProtocol函數的入參protocol在server.xml中配置

Tomcat是如何處理一次請求的 源碼版本8.0.21
Tomcat是如何處理一次請求的 源碼版本8.0.21

 setProtocol函數代碼作用:主要判斷了是否啟用Apr模式,如果啟用,那麼"HTTP/1.1"就将org.apache.coyote.http11.Http11AprProtocol這個類作為Handler,其他協定以此類推。

我們可以看到在關閉Apr模式的時候,配置"HTTP/1.1"是将Http11NioProtocol類作為Handler,Http11NioProtocol為NIO模式連接配接器,因為NIO模式涉及到生産者消費者模式,代碼略複雜,下文我們将用Tomcat7中的Http11Protocol類(BIO模式)來剖析一次請求的過程。

Tomcat是如何處理一次請求的 源碼版本8.0.21

可以看到Http11NioProtocol在構造的時候初始化了一個JIoEndpoint(通信端點)

Tomcat是如何處理一次請求的 源碼版本8.0.21

在JIoEndpoint類中我們看到其内部類Acceptor啟動一個線程,一直在循環接收請求

Tomcat是如何處理一次請求的 源碼版本8.0.21

 跟進processSocket方法可以看到用線程池做了一次調用

Tomcat是如何處理一次請求的 源碼版本8.0.21

跟進内部run方法下finally塊中handler.process(socket, SocketStatus.DISCONNECT);開始調用handler處理請求

Tomcat是如何處理一次請求的 源碼版本8.0.21

 繼續跟進發現其調用super.process(socket, status);

Tomcat是如何處理一次請求的 源碼版本8.0.21
Tomcat是如何處理一次請求的 源碼版本8.0.21

最終我們一路跟進發現調用到AbstractHttp11Processor類中 process()方法 

Tomcat是如何處理一次請求的 源碼版本8.0.21

在這個方法中我們可以看到,tomcat已經開始對request對象進行指派。

Tomcat是如何處理一次請求的 源碼版本8.0.21

最終将請求交給adapter去處理,

Tomcat是如何處理一次請求的 源碼版本8.0.21

 最終調用connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);将請求交給Engine的Pineline處理

Tomcat是如何處理一次請求的 源碼版本8.0.21

 最終通過責任鍊模式,一步步的調用到ApplicationFiterChain執行Servlet的service方法。

Tomcat是如何處理一次請求的 源碼版本8.0.21

 最終在HttpServlet類中去調用doGet方法,繼而調用到我們繼承自HttpServlet自定義的doGet方法。

繼續閱讀