Tomcat鏈接器:Coyote框架

不論Tomcat的容器設計得如何精妙,本質上Tomcat就是個http服務器,須要從socket中得到HTTP數據流;另外一方面,容器只能處理封裝好的org.apache.coyote.Request (這個類的具體用途下面會講到),從socket到Request之間須要有個轉換過程。所以,鏈接socket和容器之間的重任就交給了Coyotehtml

Coyote簡介

coyote(北美的一種狼、山狗)java

coyote是tomcat的Connector框架的名字,簡單說就是coyote來處理底層的socket,並將http請求、響應等字節流層面的東西,包裝成Request和Response兩個類(這兩個類是tomcat定義的,而非servlet中的ServletRequest和ServletResponse),供容器使用;同時,爲了能讓咱們編寫的servlet可以獲得ServletRequest,tomcat使用了facade模式,將比較底層、低級的Request包裝成爲ServletRequest(這一過程一般發生在Wrapper容器一級),這也是爲不少人津津樂道的tomcat對設計模式的一個巧妙的運用,具體過程將會在之後討論。程序員

因此,coyote本質上是爲tomcat的容器提供了對底層socket鏈接數據的封裝,以Request類的形式,讓容器可以訪問到底層的數據。web

而關於鏈接池、線程池等直接和socket打交道的事情,tomcat交給了org.apache.tomcat.util.net包的類去完成,這裏暫且不表apache

http://www.webweavertech.com/costin/archives/000421.html
這個網頁很好的描述了coyote的做用和設計思想,並介紹了其中幾個影響性能的核心類編程

org.apache.coyote

這個包裏面的主要是coyote框架的接口設計模式

Adapter

「適配器」在這裏的意思,是指「凡是使用coyote鏈接器的容器,都要實現這個接口,以便從coyote鏈接器接收請求和響應數據」,固然這裏的請求和響應是org.apache.coyote.Request和Response數組

ProtocolHandler

每一個ProtocolHandler,表明着對一種協議的支持,好比tomcat默認支持的協議有http1.1和ajp。根據支持的協議,ProtocolHandler裏面一般包含了一個實現對應協議的Handler接口的處理類,用於接收socket對象,再交給對應協議的Processor類(然而這個Processor類沒有實現Processor接口,而是實現了ActionHook接口),最後由Processor類交給實現了Adapter接口的容器(準確的說是該容器的Pipeline的第一個Valve)tomcat

Processor

這個接口已經廢棄了,一般tomcat的Processor實現類實現的接口是ActionHook。你會看到許多名爲「XXXProcessor」的類,但其實他們實現的接口倒是ActionHook服務器

ActionHook

本接口代替了Processor接口,成爲全部Processor實現類的標準接口。其方法只有一個:public void action( ActionCode actionCode, Object param);
ActionCode是一個靜態類,說白了是一堆常量(估計之後會改爲enum),即對應不一樣的ActionCode,ActionHook要做出不一樣的動做,至於param是用於傳遞一些信息的,一般會把調用者「this」傳遞進去

InputBuffer和OutputBuffer

兩個接口都只有一個方法,分別是doread和dowrite,就是把數據從ByteChunk參數讀出或者寫入ByteChunk。然而「數據」從何而來、怎樣寫進ByteChunk,還得看不一樣的類實現

Request,Response

鑑於其重要性,下面專文講述

Request和Response

Request這個類可謂tomcat的一大核心,幾乎全部connector和容器都要用到它

Request類實現了對底層http字節流的封裝,由於http本質上是從網絡過來的一串字節流,而且從邏輯上根據http協議,分紅了頭和體,其中頭部又有不少字段(包括MIME字段)。而Request的做用就是把這些字節封裝成對應的字段,而且達處處理效率的最優

所以,Request裏面大部分方法是字段的get方法(set方法很少,由於大部分字段是不可改變的),此外還有提供給容器使用的方法,如recycle、inputbuffer等等。但最關鍵的是,Request是如何提升處理效率的

對於底層的、和字節流打交道的DO(data object),性能瓶頸在於對內存的使用上(由於字節都是放在一塊塊的內存中),若是能有效的使用內存,就能有效地提升DO的性能。

若是讓咱們來實現這個Request類,估計大部分人第一反應就是用String來表示每一個http頭字段,然而String的效率之低下是絕對沒法勝任服務器的性能要求的

Request的註釋告訴咱們,它的大部分字段是「GC free」的,即不多、甚至不會被垃圾回收。杜絕了java中最大的一個性能瓶頸,Request天然性能獲得大幅提高

此外,其字段的一些耗時操做都會延遲到用戶代碼一級,也就是說,tomcat內部在使用Request時,都會盡可能保證它的字段處於原始的字節狀態(而不是圖方便處處使用String),直到用戶代碼(也就是咱們寫的servlet)須要時才進行轉換,若是用不到(其實http請求的大部分字段在咱們編程時都用不到),就不做轉換。這樣又進一步挖掘出更多的性能潛力,其思想和「延遲加載」的設計模式一模一樣。

固然,tomcat的程序員也是人也喜歡偷懶,誰都不樂意直接操縱字節數組,那樣出錯的風險也大。所以,tomcat的org.apache.tomcat.util包定義了許多底層的工具類,用於操做和維護字節數組。Request的字段們的類型爲MessageBytes就是其中的一種

而關於Response,原理和Request相似,可是Response簡單了不少,最明顯的是裏面的字段不像Request那樣爲效率絞盡腦汁,而是直接用了String,也許是Response對總體效率影響不大,亦或者當前版本的tomcat還未對其進行改造

相關文章
相關標籤/搜索