Tomcat 处理 HTTP 请求源码分析(上)【转】
原文地址:https://www.infoq.cn/article/zh-tomcat-http-request-1
很多開源應用服務器都是集成 tomcat 作為 web container 的,而且對于 tomcat 的 servlet container 這部分代碼很少改動。這樣,這些應用服務器的性能基本上就取決于 Tomcat 處理 HTTP 請求的 connector 模塊的性能。本文首先從應用層次分析了 tomcat 所有的 connector 種類及用法,接著從架構上分析了 connector 模塊在整個 tomcat 中所處的位置,最后對 connector 做了詳細的源代碼分析。并且我們以 Http11NioProtocol 為例詳細說明了 tomcat 是如何通過實現 ProtocolHandler 接口而構建 connector 的。
通過本文的學習,應該可以輕松做到將 tomcat 做為 web container 集成到第三方系統,并且自定義任何你想要的高性能的 HTTP 連接器。
1 Connector 介紹
1.1 Connector 的種類
Tomcat 源碼中與 connector 相關的類位于 org.apache.coyote 包中,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 等)的訪問性能。現在這個庫已獨立出來可用在任何項目中。Tomcat 在配置 APR 之后性能非常強勁。
1.2 Connector 的配置
對 Connector 的配置位于 conf/server.xml 文件中。
1.2.1 BIO HTTP/1.1 Connector 配置
一個典型的配置如下:
<Connector port=”8080” protocol=”HTTP/1.1” maxThreads=”150” connectionTimeout=”20000” redirectPort=”8443”其它一些重要屬性如下:
- acceptCount : 接受連接 request 的最大連接數目,默認值是 10
- address : 綁定 IP 地址,如果不綁定,默認將綁定任何 IP 地址
- allowTrace : 如果是 true, 將允許 TRACE HTTP 方法
- compressibleMimeTypes : 各個 mimeType, 以逗號分隔,如 text/html,text/xml
- compression : 如果帶寬有限的話,可以用 GZIP 壓縮
- connectionTimeout : 超時時間,默認為 60000ms (60s)
- maxKeepAliveRequest : 默認值是 100
- maxThreads : 處理請求的 Connector 的線程數目,默認值為 200
如果是 SSL 配置,如下:
<Connector port="8181" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol = "TLS" address="0.0.0.0" keystoreFile="E:/java/jonas-full-5.1.0-RC3/conf/keystore.jks" keystorePass="changeit" />其中,keystoreFile 為證書位置,keystorePass 為證書密碼
1.2.2 NIO HTTP/1.1 Connector 配置
<Connector port=”8080” protocol=”org.apache.coyote.http11.Http11NioProtocol” maxThreads=”150” connectionTimeout=”20000” redirectPort=”8443”1.2.3 Native APR Connector 配置
tcnative-1.dll 與 openssl.exe,將其放在 %tomcat%\bin 目錄下。
下載地址是:http://tomcat.heanet.ie/native/1.1.10/binaries/win32/
maxThreads=”150” connectionTimeout=”20000” redirectPort=”8443”
2 Connector 在 Tomcat 中所處的位置
2.1 Tomcat 架構
圖 2-1 Tomcat 架構
- Server(服務器) 是 Tomcat 構成的頂級構成元素,所有一切均包含在 Server 中,Server 的實現類 StandardServer 可以包含一個到多個 Services;
- 次頂級元素 Service 的實現類為 StandardService 調用了容器 (Container) 接口,其實是調用了 Servlet Engine(引擎),而且 StandardService 類中也指明了該 Service 歸屬的 Server;
- 接下來次級的構成元素就是容器 (Container),主機 (Host)、上下文 (Context) 和引擎 (Engine) 均繼承自 Container 接口,所以它們都是容器。但是,它們是有父子關系的,在主機 (Host)、上下文 (Context) 和引擎 (Engine) 這三類容器中,引擎是頂級容器,直接包含是主機容器,而主機容器又包含上下文容器,所以引擎、主機和上下文從大小上來說又構成父子關系,雖然它們都繼承自 Container 接口。
- 連接器 (Connector) 將 Service 和 Container 連接起來,首先它需要注冊到一個 Service,它的作用就是把來自客戶端的請求轉發到 Container(容器),這就是它為什么稱作連接器的原因。
故我們從功能的角度將 Tomcat 源代碼分成 5 個子模塊,它們分別是:
2.2 Tomcat 運行流程
圖 2-2 tomcat 運行流程
假設來自客戶的請求為:http://localhost:8080/test/index.jsp
3 Connector 源碼分析
3.1 Tomcat 的啟動分析與集成設想
我們知道,啟動 tomcat 有兩種方式:
- 雙擊 bin/startup.bat
- 運行 bin/catalina.bat run
它們對應于 Bootstrap 與 Catalina 兩個類,我們現在只關心 Catalina 這個類,這個類使用 Apache Digester 解析 conf/server.xml 文件生成 tomcat 組件,然后再調用 Embedded 類的 start 方法啟動 tomcat。
所以,集成 Tomcat 的方式就有以下兩種了:
- 沿用 tomcat 自身的 server.xml
- 自己定義一個 xml 格式來配置 tocmat 的各參數,自己再寫解析這段 xml,然后使用 tomcat 提供的 API 根據這些 xml 來生成 Tomcat 組件,最后調用 Embedded 類的 start 方法啟動 tomcat
個人覺得第一種方式要優越,給開發者比較好的用戶體驗,如果使用這種,直接模仿 Catalina 類的方法即可實現集成。
目前,JOnAS 就使用了這種集成方式,JBoss、GlassFish 使用的第二種自定義 XML 的方式。
3.2 Connector 類圖與順序圖
圖 3-1 Connector 相關類圖
圖 3-2 Connector 工作流程順序圖
從上面二圖中我們可以得到如下信息:
圖 3-3 自定義 connector 時需實現的 ProtocolHandler 接口
Tomcat 以 HTTP(包括 BIO 與 NIO)、AJP、APR、內存四種協議實現了該接口(它們分別是:AjpAprProtocol、AjpProtocol、Http11AprProtocol、Http11NioProtocol、Http11Protocal、JkCoyoteHandler、MemoryProtocolHandler),要使用哪種 Connector 就在 conf/server.xml 中配置,在 Connector 的構造函數中會通過反射實例化所配置的實現類:
<Connector port="8181" protocol="org.apache.coyote.http11.Http11AprProtocol " />3.3 Connector 的工作流程
下面我們以 Http11AprProtocol 為例說明 Connector 的工作流程。
轉載于:https://www.cnblogs.com/davidwang456/articles/11249466.html
總結
以上是生活随笔為你收集整理的Tomcat 处理 HTTP 请求源码分析(上)【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手写一个迷你版的 Tomcat 喵【转】
- 下一篇: Tomcat 处理 HTTP 请求源码分