聶永的博客

          記錄工作/學習的點點滴滴。

          HTTP/2筆記之連接建立

          前言

          HTTP/2協議在TCP連接之初進行協商通信,只有協商成功,才會涉及到后續的請求-響應等具體的業務型數據交換。

          HTTP版本標識符

          • h2,基于TLS之上構建的HTTP/2,作為ALPN的標識符,兩個字節表示,0x68, 0x32,即https
          • h2c,直接在TCP之上構建的HTTP/2,缺乏安全保證,即http
          • 在HTTP/2 RFC文檔出現之前,以上版本字段需要添加上草案版本號,類似于h2-11,h2c-17

          HTTP/2 請求過程

          針對直接建立在標準TCP之上HTTP2,在未知服務器是否提供HTTP/2支持之前,可以依賴現有HTTP/1.1進行試探。

          HTTP版本的請求內容

          1. 客戶端發起請求,只有請求報頭:
            GET / HTTP/1. 1
            Host: server. example. com
            Connection: Upgrade, HTTP2-Settings
            Upgrade: h2c
            HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
            
          2. 服務器若不支持HTTP/2,直接按照HTTP/1.1響應即可
            HTTP/1. 1 200 OK
            Content-Length: 243
            Content-Type: text/html
            . . .
            
          3. 服務器支持HTTP/2,通知客戶端一起切換到HTTP/2協議下吧

            HTTP/1. 1 101 Switching Protocols
            Connection: Upgrade
            Upgrade: h2c
            
            [ HTTP/2 connection . . .
            
          4. 101響應空行之后,服務器必須發送的第一個幀為SETTINGS幀(其負載可能為空)作為連接序言
          5. 客戶端接收到101響應后,也必須發送一個序言作為響應,其邏輯結構:
            PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 純字符串表示,翻譯成字節數為24個字節
            SETTINGS幀                       // 其負載可能為空
            
            服務器端和客戶端所發送的連接序言有所不同。
          6. 客戶端可以馬上發送請求幀或其它幀過去,不用等待來自服務器端的SETTINGS幀
          7. 任一端接收到SETTINGS幀之后,都需要返回一個包含確認標志位SETTIGN作為確認
          8. 其它幀的正常傳輸

          HTTP/2的直接連接

          客戶端預先知道服務器提供HTTP/2支持,可以免去101協議切換的流程開銷。 具體流程:

          1. 客戶端必須首先發送一個連接序言,其邏輯結構:
            PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 純字符串表示,翻譯成字節數為24個字節
            SETTINGS幀                       // 其負載可能為空
            
          2. 發送完畢序言之后,客戶端可以不用等待來自服務器端響應,馬上發送HTTP/2其它幀
          3. 服務器端接收到客戶端的連接序言之后,需要發送一個SETTINGS幀作為連接序言
          4. 任一端接收到SETTINGS幀之后,都需要返回一個包含確認標志位SETTIGN作為確認
          5. 其它幀的正常傳輸

          HTTPS版本建立連接

          HTTP/2安全版本在TLS上構建,協商采用的ALPN擴展協議,采用“h2”作為協議標識符(http版本則是“h2c”)。一定程度上可認為不存在試探是否支持或直接連接的煩惱,因為這個過程直接在TLS層協商而成。

          流程如下:

          1. 客戶端和服務器端TLS層協商
          2. 客戶端發送連接序言(同上表示,PRI + SETTINGS)
          3. 接收到客戶端連接序言之后,服務器端發送連接序言
          4. 雙方各自確認SETTINGS幀
          5. 其它幀的正常傳輸

          HTTPS和HTTP Upgrade方式協商

          HTTPS協商是強制,封裝在TLS之上ALPN擴展實現,HTTP只有非直接連接方式才會存在通過101 協議切換方式進行升級。

          這里有一張圖形象說明其流程。

          統一的連接過程

          這里不論是HTTP還是HTTPS,在兩端成功協商之后(或HTTP的直接連接),其連接過程都是一樣的

          注意事項

          1. 客戶端發起的HTTP/1.1請求,其流標識符為1,默認優先級;半關閉“half closed”狀態,一旦完成HTTP/2的連接,將被應用于響應
          2. 文檔提到的客戶端可以通過HTTP Alternative Services(簡稱為[ALT-SVC],類似于CNAME機制)獲得通知服務器是否支持HTTP/2,但目前看來僅僅是草案建議而已
          3. 連接序言用于最后兩端協商確認雙方要使用HTTP/2協議,建立初始化的HTTP/2連接環境
          4. 客戶端若知服務器支持HTTP/2,可免去通過HTTP/1.1 101協議切換方式進行升級,在建立連接后即可發送序言,否則只能在接收到服務器端101響應后發送序言
          5. 建立在TLS上的HTTP/2通過ALPN擴展協商機制取代101協議切換
          6. 連接序言所包含的SETTINGS幀其負載可以為空
          7. 針對一個TCP連接,服務器第一個要發送的幀必須是SETTINGS幀
          8. 為了避免不必要延遲,客戶端可以在發送完畢序言之后發送幀數據,不用等待來自服務器端的序言SETTINGS幀
          9. 客戶端接收到服務器端作為序言的SETTINGS幀,需要遵守其設定
          10. 在一些環境下需要提供一個順序機制,允許服務器在客戶端發送業務幀之前發送SETTINGS,這需要客戶端配合
          11. 客戶端和服務器端任何一方接收到無效連接序言需要拋出PROTOCOL_ERROR類型連接錯誤,若收到GOAWAY幀,可忽略

          小結

          HTTP/2連接的建立協商機制比HTTP/1.1稍微復雜了一些。

          對比明文版的HTTP/1.1和HTTP/2完成一次請求-響應:

          1. HTTP/1.1在建立建立之后,只需要發送請求報文數據
          2. HTTP/2客戶端需要在連接建立之初馬上發送一個連接序言過去,然后才是正常請求
          3. 兩端(客戶端+服務器端)的兩次完整的連接序言+確認的交互流程,多了兩次往返過程

          在弱網絡環境下,會不會加重網絡負載,只能拭目一看了。

          引用

          1. 《Implementing HTTP/2 client in 60 minutes》

          posted on 2015-03-18 13:54 nieyong 閱讀(13626) 評論(0)  編輯  收藏 所屬分類: HTTP

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2015年3月>
          22232425262728
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 陆丰市| 东方市| 高要市| 银川市| 江口县| 新乡市| 元阳县| 肥东县| 惠来县| 托克逊县| 四平市| 安庆市| 麻城市| 错那县| 鹤庆县| 武山县| 奇台县| 延安市| 墨竹工卡县| 朝阳区| 高雄市| 桐梓县| 舞钢市| 宁陵县| 二连浩特市| 靖江市| 札达县| 衡东县| 兴和县| 堆龙德庆县| 盐边县| 额尔古纳市| 图木舒克市| 曲松县| 万安县| 博白县| 油尖旺区| 新乐市| 桐乡市| 吴江市| 宜春市|