2014年11月6日

下一代HTTP標準:HTTP 2.0

作者/王琨堯
[發表日期:2014/11/3]
前言

網際網路工程任務組(Internet Engineering Task Force)於1990年推出第一版HTTP 1.0,1999再推出的HTTP 1.1版,讓網路世界有了溝通的共通協定,並加速了網路世界的發展。24年後的今天,人們已經習慣網路帶來的方便,隨著網路世界的蓬勃發展,網站功能越來越多及複雜,使得網頁的載入時間越來越長,因此為了提升網路的載入效能,IETF在2012年採用Google SPDY V2版本作為HTTP 2.0出發點,同一時間SPDY依然並行持續發展的,在V3中更新的幀的版本及在V4版本中改善了優先權、流程控制及Server Push。本文將介紹HTTP 2.0 關鍵提升網路存取效能原理及探討新的標準所帶來的效應。

一、HTTP 2.0特點

HTTP 2.0 介紹
  • 為何需要HTTP 2.0
    經過十五年的技術演進,現今的單一網頁對於伺服器送出的檔案載入要求次數和內容大小已經不再像以往,就以最大家最常用頁面也很簡單的Google首頁,1999年Google首頁整體載入要求未壓縮的是14K,10年後的Google首頁未壓縮成長至600k。從整體的統計來看,如圖一,從2011/8/15至2014/8/15的數據觀察,網頁的平均傳輸大小從816k Byte成長至1855k Byte,成長了43%。而網頁送出的平均Request從83個到97個,成長了85%。


    《圖一》傳輸大小與要求總數


    由上圖看來,十年前的傳輸協定已經不敷現今的網頁使用,因此需要更快的方式讓網頁載入不會因為request數量變大而變慢,老舊的傳輸方式需要被改善。
  • Starting HTTP 2.0
    在網路七層中,HTTP 2.0的工作層為應用層(Application layer),規範基於TCP傳輸協定負責伺服器與終端之間的封包傳輸方式。HTTP 2.0與HTTP 1.1版本一樣使用HTTP通訊埠為80,https則使用通訊埠443。
    了解運作原理之前,因為目前普遍還是使用HTTP 1.1,我們必須先了解新的HTTP 2.0如何去建立。透過一個普通沒有加密的協定建立一個HTTP 2.0連線需要點額外的動作,伺服器在初始建立連線時會透過Application Layer Protocol Negotiation(ALPN)來確認是否建立HTTP2.0 連線。Client端會先發出一個HTTP 1.1的連線封包,裡面除了原始送出的request還會包含了請求傳輸協定升級HTTP 2.0的標頭部分,標頭內容如下:



    若嘗試連線的伺服器端並不支援HTTP 2.0,伺服器會自動忽略h2c的tag並回傳封包內容如下:


    支援HTTP 2.0的伺服器會回傳101代碼(切換協定)以表示支援,格式如下:


    在此之後的封包傳輸皆以HTTP 2.0協定傳輸。從伺服器端送出的第一個HTTP 2.0封包為設定幀(Setting Frame)。設定幀中包含了伺服器端對於HTTP 2.0的偏好設定與限制設定,用來設定規範終端的通訊行為,接收端負責確認內容,在確認後設定幀的乘載內容(payload)會被清空。

    設定幀除了在第一次建立連線後傳送,當連線結束生命週期後重新連線會在被重新傳送一次,它通常只會在連線建立剛開始傳送,不會單獨被傳送。設定幀的識別標頭必須為0X0,若接收時發現並不是0X0,則會回傳協定錯誤(PROTOCOL_ERROR)中的連線錯誤。《圖二》為設定幀資料格式,包含了16位元的識別幀與32位元的資料。


    《圖二》設定幀的格式
  • HTTP 2.0 Connection Preface
    在建立TCP連線及確認伺服器端及客戶端使用HTTP2.0後,雙方必須送出最後的連線Preface作為確認。在做此確認後,初始化時會送出設定幀,伺服器端與客戶端會送出不同的Preface。
    從客戶端送出的連線Preface為一個24位元的16進制表示:


    為了避免多餘的延遲時間,客戶端會在送出連線preface後,在收到伺服器傳來的preface之前傳送額外的幀到伺服器端。


HTTP 2.0 架構 (HTTP 2.0 Frames) 
  • HTTP 2.0 架構格式 (HTTP 2.0 Frame Format)
    HTTP 2.0與HTTP 1.1其中一個不同地方在於傳送資料的格式有所改變。在HTTP 2.0中傳送資料方式是使用幀(Frame),每一個幀的標頭大小為固定為72位元(9-octet),乘載的資料量初始設定最大為214 (16,384),若資料量大於限制則無法被傳送,除非更改SETTINGS_MAX_FRAME_SIZE設定。傳送資料大於限制會回傳協定錯誤。

    幀標頭包含了幾個項目,如《圖三》。Length為一個24位元的數字字串,做為紀錄目前幀的大小,預設大小為214。Type為8位元大小,用來判別幀的格式,實際在應用上若Type的值是空的或未知的,則會被接收忽略。Flags為8位元大小保留給特定的幀使用,是一布林值。當幀被送出時預設值為0。R為一位元保留位置,送出時與設為0,接收時則可以被忽略。Stream Identifier為31位元串流識別。從伺服器端送出的幀在這個欄位的值永遠會是雙數,反之從伺服器端送出的都會是奇數。若值為0,則為連線控制訊息。


    《圖三》幀格式


    當一個幀的乘載資料過大或是不夠空間去乘載必要性的資料,終端都會發出Frame_Size_Error連線錯誤。
  • 標頭壓縮與解壓縮 (Header Compression and Decompression)
    在舊有的HTTP 1.1中也是有壓縮技術,但是主要用來做檔案壓縮。新的通訊協定標準中,訴求的是讓資料傳遞間速度加快,除了改進傳遞的規則,若能丟棄傳遞過程中多餘冗長或重複性的資料,包袱相對變小,在相同的頻寬下若資料量變小,傳送與接收的速度則會相對縮短。

    在封包傳輸中,標頭會包含一系列的傳遞資訊,在HTTP 2.0的環境中傳輸時,會根據HPACK規範將標頭壓縮。最初SPDY使用DEFLATE作為壓縮資料格式,DEFLATE最後版本為1996年五月,此規範提供高效率的資料壓縮方式,使用於標頭可以確切地達到丟棄多餘的資訊,但在實際運作上會造成CHIME攻擊,資訊安全上確有疑慮。在資料壓縮後儘管的資料儘管可能包含一些損壞的位元,但在認證資訊上仍然是可讀性的,因此在恢復連線認證資訊時會讓駭客有機會作存取Session的攻擊,造成更進一步的安全性攻擊。

    而HTTP2.0所使用的HPACK規範同樣可以將標頭壓縮移除多餘及重複性的資訊,同時解決了資訊安全的問題。在HPACK規範中,並沒有特別提到任何壓縮演算法,此規範主要用來告知編碼器如何運作。

    在運作上標頭會被轉換成有順序性的名稱和值,每一副名稱與值被分割成八位元後,有順序的放於標頭列表中。在HPACK中使用了兩種表格來儲存資訊,一個是靜態表格,主要用來預先定義標頭名稱及包含一些共同使用的欄位,這些欄位大都是空值。另一個是動態表格,是由一個標頭的列表所組成,資料更新方式是以先進先出的方式,而這表格初始時是空值,每次新增的資料會在標頭區塊進行解壓縮。動態表格中的資料是可以重複的,因此對於編譯器來說不能認定為一個錯誤資料。

    透過HPACK的壓縮處理後標頭區塊,會被分割成一個或多個八位元序列成為標頭區塊片段(Header block fragments),其中包含Cookie資訊的表頭會有不同的方式處理。經處理後的標頭區塊片段,會與封包中的資料部分及PUSH_PROMISE或CONTINUATION一起被傳輸。

    一個完整的標頭區塊(Header Block)會有兩種結構:
      1.單一的Header或PUSH_PROMISE,及一個END_HEADERS旗標。
      2.單一的Header或PUSH_PROMISE,一個END_HEADERS旗標及一個或多個CONTINUATION 幀;最後一個CONTINUATION 幀會包含END_HEADERS旗標。


串流與多工 (Streams and Multiplexing)

HTTP是一個訊息互傳的溝通協定,當用戶端發送Request給伺服器端時,這時用戶端必須等待伺服器的回覆才能再繼續送出Request,這樣的過程通常會花費大約兩百萬秒或是更多,這時也許頻寬並不壅塞,但無論無何都需要等待收到Response後才能繼續,如果一個Response發生了延遲狀況,後面的動作將會延遲更久,發生所謂的Headline blocking,封包來往都需要有順序及需要等待而造成的壅塞。

而在HTTP 2.0 中串流(Stream)解決了這項問題,串流是一項伺服器與終端間獨立、雙向序列幀交換的連線方式,使得終端可以同時發出多個Request,而伺服器也可以同時不依照順序地回傳多個Response,甚至可以只傳送部分的封包並且在終端進行組裝,如此的方式可以有效的降低封包互相傳遞時等待的時間。

  • 串流狀態 (Stream States)
    不同的狀態代表著串流現在可以處理的事情,在串流狀態中分為七種,分別為閒置(idle)、保留(Reserved)、開啟(Open)、半關閉(Half Close)及關閉(Closed)。每個狀態都是雙向的,因此都會因為接收或送出而改變狀態。

    閒置狀態是建立串流連線後的第一個狀態,在這狀態中不會有任何的封包交換,而這個狀態只接受Headers及PUSH_PROMISE兩種控制幀,閒置狀態在送出或收到Headers後會改變為開啟的狀態(Open)。若是送出或收到PUSH_PROMISE則改變狀態為保留狀態,在這狀態還分為本機及遠端。

    當狀態為開啟時,兩端可以互相交換任何類型的幀。若終端送出帶有End_Stream旗標的幀時,狀態則會改為Half Close,這狀態同時也分為本機與遠端。
  • 串流並行處理(Stream Concurrency)
    HTTP 2.0資料傳輸靠的是串流,而每一次建立傳輸能建立一條以上的串流通道,雙方都能透過送出設定幀裡的SETTINGS_MAX_CONCURRENT_STREAMS 參數來設定最多能建立幾條通道,會對於串流數計數的狀態分別是開啟及半關閉時候,只有在保留的狀態不做計數的動作。SETTINGS_MAX_CONCURRENT_STREAMS並沒有最大值,若是為了停止收到Request而設為0,則建議直接斷掉連線。


流程控制 (Flow Control) 
  • 流程控制概念 (Flow Control Principles)
    當透過TCP連線並使用串流做為多工傳輸時,會造成連線壅塞。因此需要建立一套機制來確保在相同的連線上,不同的串流不會互相干擾。流程控制的概念是應用在hop by hop,一個hop代表通過一個路由,因此流程控制會因為不同的路由而有所不同,它並不是建立在點對點的環境上。

    在流程控制中扮演最重要的角色的是WINDOW_UPDATE幀。初始的WINDOW_UPDATE長度為32位元組,除了1位元為保留位元外,其餘31位元皆為內容。在規範中只定義了幀送出時的格式,並沒有定義如何接收或送出的值,這部分適用於任何演算法去運作。流層控制只運作在單一的串流或是整體的連線,如果接收端收到的WINDOW_UPDATE為0則會送出協定錯誤(PROTOCOL_ERROR)。
  • 串流優先權 (Stream priority)
    終端可以透過Header幀來指定狀態為開啟的串流優先順序,串流中會有一個優先權幀(PRIORITY frame)可用來改變串流優先權。優先權的目的在於當終端在管理並行進行的串流時可以用來做資源的分配,在傳輸量有限的情況下會希望串流傳輸較重要的幀。但在實際應用上還是要看程序上的順序,這優先權並無法保證單一串流於任何特別的程序或是傳輸在順序上相對應到另一個串流,終端並無法強迫接駁端的串流以特定的順序工作。優先權是一個選擇性設定,若沒特別的設定它會依照預設的去執行。
  • 串流相依性 (Stream Dependencies)
    在一個連線建立後會建立一個以上的串流來傳送資料,而每一個串流之間則是有相依性的,串流中會有包含判別相依性的資訊。


二、HTTP 2.0帶來的影響

在看完各項技術的細節後,這一章節討論的是新的傳輸協定帶來的衝擊。新的傳輸協定不僅提升了網站應用的效率及些許的改變網站設計,以網站設計師來說,過去設計網頁時為了提升頁面開啟的速度會利用一些技巧,例如在網站中將圖片切割數塊來提升下載速度,或是將Java Script或CSS檔案整合在一起,在使用新的通訊協定後也不需要這麼費工了!對於使用者來說,瀏覽網頁時開啟速率會比起以往快一倍的時間,絕對可以提高的使用者經驗(Quality of Service)。

當然新的協定也有其他使用上的顧慮,不可能一夕之間大家都開始使用它,數以千億台的主機需要升級支援二進制傳輸或是透過SSL傳輸,現階段伺服器支援SSL加密傳輸並不普及。關於這點兩大瀏覽器Firefox及Chrome日前表示他們目前只會支援HTTP 2.0透過TLS傳輸,因為部屬新版的HTTP是一件困難的事情,所以當傳輸環境使用HTTP 2.0時,在網路中介層中的一些其他協定不改變的狀況下,瀏覽器可以提供元件作為間接的動作。
以下為HTTP 2.0協定中用來提升傳輸效率方式的總整理:
    1.標頭壓縮
    過去HTTP 1.1中雖然有壓縮技術於其中,但是最主要用來壓縮傳遞的資料,因此在HTTP 1.1中的request及response都包含了至少100MB以上的標頭,但大部分卻又是重複性的資料。在HTTP 2.0中的壓縮技術使用於標頭上,讓資料不再重複性的被傳送,以降低次的傳輸量。

    2.多工傳輸 & 優先權
    現行的HTTP 1.1傳輸協定中,需要終端主動的向伺服器提出資源的要求,而提出要求後還需要等待伺服器的回應後才又送出下一個要求,在新的HTTP 2.0改善了這樣傳輸方式,改用串流方式傳輸。一個連線可以建立多個串流,單一串流中可以達到雙向傳輸且不須依照順序的接收片段資料,如此能縮短接收資料時間並大幅度的提升載入網頁的速度。

    3.伺服器主動推送資料(Server Push)
    以往終端需要送出request去給伺服器要求資源,但在HTTP 2.0中伺服器可以主動的向終端送出資源,伺服器通常會主動送出網頁的樣式表CSS及HTML資源,這樣的技術可以使得雙方溝通的次數降低,但網頁載入資源的速度更快。

    4.資料加密與二進制資料格式
    在HTTP 2.0環境下,雙方傳遞資料透過二進制資料格式及SSL方式作為傳輸協定,如此二進制資料加上SSL的加密必定能提升資訊安全的程度。若要使用工具查看封包,像是Wireshark之類的網路監測工具提供了外掛程式解析二進制內容。


結論

HTTP 1.1已經使用超過十年的時間,這十年間的網頁變化很大,現今的網頁傳送出的request數量已多於以往數倍,老舊的HTTP 1.1傳輸協定已經不敷使用。以SPDY為主軸的HTTP 2.0的推出的目的就是要降低50%的網頁載入的等待時間,使用標頭壓縮、多工傳輸、伺服器主動資源推送等等的方式來降低雙方溝通的次數或是降低多餘的傳送資料。2014年11月HTTP 2.0協定將會正式成為新一代標準,期待未來它能為網際網路帶來下一個十年的榮景。

參考資料


沒有留言:

張貼留言

<Javascript> How to uncompressed GZIP at front-end using Javascript

It's been a while I haven't share my coding work. In this article I would like to share how to receive a Gzip file via stream, unzip...