目錄
1.Tomcat容器構成
2.Tomcat是如何接收一次請求的
1.Tomcat容器構成
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中配置
setProtocol函數代碼作用:主要判斷了是否啟用Apr模式,如果啟用,那麼"HTTP/1.1"就将org.apache.coyote.http11.Http11AprProtocol這個類作為Handler,其他協定以此類推。
我們可以看到在關閉Apr模式的時候,配置"HTTP/1.1"是将Http11NioProtocol類作為Handler,Http11NioProtocol為NIO模式連接配接器,因為NIO模式涉及到生産者消費者模式,代碼略複雜,下文我們将用Tomcat7中的Http11Protocol類(BIO模式)來剖析一次請求的過程。
可以看到Http11NioProtocol在構造的時候初始化了一個JIoEndpoint(通信端點)
在JIoEndpoint類中我們看到其内部類Acceptor啟動一個線程,一直在循環接收請求
跟進processSocket方法可以看到用線程池做了一次調用
跟進内部run方法下finally塊中handler.process(socket, SocketStatus.DISCONNECT);開始調用handler處理請求
繼續跟進發現其調用super.process(socket, status);
最終我們一路跟進發現調用到AbstractHttp11Processor類中 process()方法
在這個方法中我們可以看到,tomcat已經開始對request對象進行指派。
最終将請求交給adapter去處理,
最終調用connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);将請求交給Engine的Pineline處理
最終通過責任鍊模式,一步步的調用到ApplicationFiterChain執行Servlet的service方法。
最終在HttpServlet類中去調用doGet方法,繼而調用到我們繼承自HttpServlet自定義的doGet方法。