HTTP2 學習

1、HTTP1.x存在的問題css

      Http1.0時Connection沒法複用,同一時間一個Connection只能處理一個request。Http1.1引入了Request pipelining來解決這一問題,Request pipelining。html

  Requestpipeling在FIFO基礎上支持同一Connection併發處理多個Request,這裏的FIFO是指Http Response發送順序必須與Request的發送順序保持一致。
  詳情前往https://en.wikipedia.org/wiki/HTTP_pipelininggit

  然而它並不完美,仍然有HOL Blocking問題。github

     

  所謂的行首阻塞是因於FIFO的緣由,致使後面的Reponse因爲其以前的Response因爲資源搶佔等緣由沒法輸出而Block。編程

  因爲這樣的限制,HTTP/1.0及HTTP/1.1時代須要對Server端建立多個鏈接,經過提升併發度來下降Latency。windows

  另外Http2支持Header壓縮,而Header壓縮在此前是不支持的,此前通常是對body進行gzip壓縮。瀏覽器

 

2、HTTP2的解決方案緩存

  HTTP2在協議上真正要求不一樣的Request能夠在同一個Connection上交錯進行,真正作到多路複用。所帶來的好處顯而易見,更少的Connection,更好的併發,更高效的網絡資源利用。服務器

  支持流量控制及請求優先級,使得重要的請求優先獲得處理,這一點對於應用來講是個大的優化點,以體驗爲目標,對不一樣的請求劃分優先級以及流量控制,好比異步加載的內容重要性低,能夠設置較低優先級。可是我的以爲這一點要作好很難,要依賴於瀏覽器,應用服務器,應用程序三個地方都有很是好的實現,是不是合理的實現還須要好的度量平臺,視效果而定。網絡

  Server Push機制支持Server端應用程序能夠預先輸出內容暫未須要的內容,從而下降潛在的延時。舉例:能夠把css內容與html內容同步輸出,而不須要等待html徹底輸出後,瀏覽器再加載css。

  支持對Http Header進行壓縮。

  高效的二進制格式(相對文本格式)傳輸。

3、原理分析

   

  將經過Jetty源碼來分析Jetty如何支持Http2的
  Jetty源碼地址:git://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git

  A. Jetty.io&Jetty.server主要類結構圖:

Jetty.io主要是對EndPoint及Connection的定義和基本實現,Jetty.server實現了絡的交互過程,包裝了Socket,Channel,多路複用等實現。這兩個包一塊兒對應用程序端或協議格式端提供了網絡交互過程,從而實現網絡交互過程對於協議及應用的透明。

B. 與Http2協議的結合:

  Jetty Basic如上圖已經介紹,HTTP2的實現只擴展ServerConnection,ServerConnectionFactory便可,至關於Jetty內核上增長插件,擴展性好,另外也不須要關注網絡細節

C. 對重點類的重點解讀:

 

類名 職責 詳細介紹
HTTP2Flusher Frame輸出控制類 重點說明:
HTTP2Flusher類中保存了各類Entry隊列,Entry中包含Frame數據,其對應的Stream引用,以及對應的CallBack。
主要屬性: 
Queue<WindowEntry> windows,WindowUpdateFrame類型的保存隊列
ArrayQueue<Entry> frames,Frame數據隊列 
主要方法:
window(), prepend(), append(), remove()等都是針對如上Queue的操做
process()真正執行Frame的輸出。首先執行Window隊列,將Window的窗口設置數據寫入到對應的Stream或Session中;而後執行WindowsSize的限流邏輯,若對應的Session或Stream當前WindowSize不大於0,則不發送Frame,不然將WindowSize減去當前Frame的Size,應用於下次限流。最後調用Session中的EndPoint類的write方法將Frame輸出
FlowControlStrategy 流控接口定義 重點說明: 
其實現類主要實現了依據發送或接收的Frame的數據length,依據固定策略改寫Session及Stream的WindowSize,以及Stream另外一端EndPoint對於WindowSize的要求,完成輸科和輸出限流的完整邏輯
Http2Session ISession的實現類 主要屬性:
1. EndPoint endPoint, 表徵了此Session的網絡端點,對於網絡的操做經過調用endPoint的方法實現
2. Generator generator,用於按需生成各類格式的Frame,Frame被最終寫入endPoint中 
3. Listener listener,Session中被動接口的邏輯實現,面向接口編程,支持多種實現
4. FlowControlStrategy flowControl前面已經講述
5. HTTP2Flusher flusher前面也已講述
主要方法:
1.newStream(),建立新的流對象,以及HeaderFrame,將流寫入Session的流緩存中,流緩存經過ConcurrentHashMap實現;並將流和HeaderFrame追加到Http2Flusher對象的ArrayQueue中;
2. push(), settings(), ping(), reset()的實現雷同,最終都是將對應格式的Frame放入Http2Flusher的ArrayQueue中。Http2Flusher是真正輸出Frame的控制類。
3. onData(),接收DataFrame時的處理方法,首先更新當前FlowControl對象中的WindowSize,並執行Window限流邏輯,若未超出限流控制,則調用Stream的處理方法處理接收到的數據,不然直接丟棄當前Frame,最後將WindowSize恢復以前值
4. onHeaders()接收HeaderFrame時的處理方法,抽象方法,交由子類實現
5. onPriority(),Jetty默認未支持客戶端發起的對優先級的支持
6. onReset(), onSettings(),onPing(),onGoAway(),onWindowUpdate(),onConnectionFailure()執行對應邏輯,經過Listener接口,支持對於這些請求數據的自定義實現
HTTP2Stream IStream的實現類 重點說明: 
實現了IStream的主動接口及其被動接口Stream.Listener。其主動接口通常是經過調用對應的ISession接口實現
HTTP2ServerSession 繼承HTTP2Session,實現Server端Session特有的邏輯 重點說明:
特有邏輯包括ServerSession在接收onPreface時,需回覆一個Settings Frame;在接收Headers請求時需建立RemoteStream對象;當接收ServerPush時,報出異常,HTTP2中Client不能向Server發送Server Push。
DataFrame HTTP2協議的各類數據格式的封閉 重點說明: 
針對不一樣的數據格式,如ServerPush,Preface等,有對應的子類實現
DataGenerator 構建如上的DataFrame 重點說明:
對於不一樣的數據格式有不一樣的子類實現
parser包 對接收的數據格式進行解析 重點說明:
對接收的數據格式進行解析

 

4、如何實現HTTP2

 

HTTP2還未被全部瀏覽器所支持,所以在實施時要支持多種協議並存.

須要Http Server端支持HTTP2協議,據我所知Tengine還沒有支持,已支持的Server列表https://github.com/http2/http2-spec/wiki/Implementations

若要充分利用HTTP2的全部優勢,須要在應用程序端(甚至是JAVA)的輸出行爲做智能處理,如經過大數據來分析哪些資源適合用Server Push並行輸出,哪些資源優先級能夠隱藏低,如何在性能與複雜度及維護成本之間作出平衡,須要業內更多的人努力和嘗試,

相關文章
相關標籤/搜索