Jetty基本原理

參考與博客:
https://my.oschina.net/liting/blog/420422

Jetty 的基本架構

Jetty 目前的是一個比較被看好的 Servlet 引擎,它的架構比較簡單,也是一個可擴展性和非常靈活的應用服務器,它有一個基本數據模型,這個數據模型就是 Handler,所有可以被擴展的組件都可以作爲一個 Handler,添加到 Server 中,Jetty 就是幫你管理這些 Handler。

Jetty 的基本架構

下圖是 Jetty 的基本架構圖,整個 Jetty 的核心組件由 Server 和 Connector 兩個組件構成,整個 Server 組件是基於 Handler 容器工作的,它類似與 Tomcat 的 Container 容器,Jetty 與 Tomcat 的比較在後面詳細介紹。Jetty 中另外一個比不可少的組件是 Connector,它負責接受客戶端的連接請求,並將請求分配給一個處理隊列去執行。
這裏寫圖片描述

Jetty 中還有一些可有可無的組件,我們可以在它上做擴展。如 JMX,我們可以定義一些 Mbean 把它加到 Server 中,當 Server 啓動的時候,這些 Bean 就會一起工作。
這裏寫圖片描述
從上圖可以看出整個 Jetty 的核心是圍繞着 Server 類來構建,Server 類繼承了 Handler,關聯了 Connector 和 Container。Container 是管理 Mbean 的容器。Jetty 的 Server 的擴展主要是實現一個個 Handler 並將 Handler 加到 Server 中,Server 中提供了調用這些 Handler 的訪問規則。

整個 Jetty 的所有組件的生命週期管理是基於觀察者模板設計,它和 Tomcat 的管理是類似的。下面是 LifeCycle 的類關係圖
這裏寫圖片描述

Handler 的體系結構

前面所述 Jetty 主要是基於 Handler 來設計的,Handler 的體系結構影響着整個 Jetty 的方方面面。下面總結了一下 Handler 的種類及作用:
這裏寫圖片描述
Jetty 主要提供了兩種 Handler 類型,一種是 HandlerWrapper,它可以將一個 Handler 委託給另外一個類去執行,如我們要將一個 Handler 加到 Jetty 中,那麼就必須將這個 Handler 委託給 Server 去調用。配合 ScopeHandler 類我們可以攔截 Handler 的執行,在調用 Handler 之前或之後,可以做一些另外的事情,類似於 Tomcat 中的 Valve;另外一個 Handler 類型是 HandlerCollection,這個 Handler 類可以將多個 Handler 組裝在一起,構成一個 Handler 鏈,方便我們做擴展。

Jetty 的啓動過程

Jetty 的入口是 Server 類,Server 類啓動完成了,就代表 Jetty 能爲你提供服務了。它到底能提供哪些服務,就要看 Server 類啓動時都調用了其它組件的 start 方法。從 Jetty 的配置文件我們可以發現,配置 Jetty 的過程就是將那些類配置到 Server 的過程。下面是 Jetty 的啓動時序圖:

這裏寫圖片描述
因爲 Jetty 中所有的組件都會繼承 LifeCycle,所以 Server 的 start 方法調用就會調用所有已經註冊到 Server 的組件,Server 啓動其它組件的順序是:首先啓動設置到 Server 的 Handler,通常這個 Handler 會有很多子 Handler,這些 Handler 將組成一個 Handler 鏈。Server 會依次啓動這個鏈上的所有 Handler。接着會啓動註冊在 Server 上 JMX 的 Mbean,讓 Mbean 也一起工作起來,最後會啓動 Connector,打開端口,接受客戶端請求,啓動邏輯非常簡單。
接受請求

Jetty 作爲一個獨立的 Servlet 引擎可以獨立提供 Web 服務,但是它也可以與其他 Web 應用服務器集成,所以它可以提供基於兩種協議工作,一個是 HTTP,一個是 AJP 協議。如果將 Jetty 集成到 Jboss 或者 Apache,那麼就可以讓 Jetty 基於 AJP 模式工作。下面分別介紹 Jetty 如何基於這兩種協議工作,並且它們如何建立連接和接受請求的。

基於 HTTP 協議工作

如果前端沒有其它 web 服務器,那麼 Jetty 應該是基於 HTTP 協議工作。也就是當 Jetty 接收到一個請求時,必須要按照 HTTP 協議解析請求和封裝返回的數據。那麼 Jetty 是如何接受一個連接又如何處理這個連接呢?

我們設置 Jetty 的 Connector 實現類爲 org.eclipse.jetty.server.bi.SocketConnector 讓 Jetty 以 BIO 的方式工作,Jetty 在啓動時將會創建 BIO 的工作環境,它會創建 HttpConnection 類用來解析和封裝 HTTP1.1 的協議,ConnectorEndPoint 類是以 BIO 的處理方式處理連接請求,ServerSocket 是建立 socket 連接接受和傳送數據,Executor 是處理連接的線程池,它負責處理每一個請求隊列中任務。acceptorThread 是監聽連接請求,一有 socket 連接,它將進入下面的處理流程。

當 socket 被真正執行時,HttpConnection 將被調用,這裏定義瞭如何將請求傳遞到 servlet 容器裏,有如何將請求最終路由到目的 servlet,關於這個細節可以參考《 servlet 工作原理解析》一文。

下圖是 Jetty 啓動創建建立連接的時序圖:
這裏寫圖片描述
Jetty 創建接受連接環境需要三個步驟:

創建一個隊列線程池,用於處理每個建立連接產生的任務,這個線程池可以由用戶來指定,這個和 Tomcat 是類似的。
創建 ServerSocket,用於準備接受客戶端的 socket 請求,以及客戶端用來包裝這個 socket 的一些輔助類。
創建一個或多個監聽線程,用來監聽訪問端口是否有連接進來。
當建立連接的環境已經準備好了,就可以接受 HTTP 請求了,當 Acceptor 接受到 socket 連接後將轉入下圖所示流程執行:
這裏寫圖片描述
Accetptor 線程將會爲這個請求創建 ConnectorEndPoint。HttpConnection 用來表示這個連接是一個 HTTP 協議的連接,它會創建 HttpParse 類解析 HTTP 協議,並且會創建符合 HTTP 協議的 Request 和 Response 對象。接下去就是將這個線程交給隊列線程池去執行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章