HTTP有兩個主要的缺點:安全不足和性能不高。
HTTPS,通過引入SSL/TLS在安全上達到了“極致”,但在性能提升方面卻是乏善 可陳,只優化了握手加密的環節,對於整體的數據傳輸沒有提出更好的改進方案,還只能依賴於“?連 接”這種“落後”的技術。Google率先發明了SPDY協議,並應用於 自家的瀏覽器Chrome,打響了HTTP性能優化的“第壹槍”。隨後互聯網標準化組織IETF以SPDY為基礎,綜合其他多方的意?,終於推出了HTTP/1的繼任者,也就是今 天的主?“HTTP/2”,在性能方面有了壹個大的?躍。
由於HTTPS已經在安全方面做的非常好了,所以HTTP/2的唯壹目標就是改進性能。但它不僅背負著眾多的期待,同時還背負著HTTP/1龐大的歷史包袱,所以協議的修改必須小心謹慎,兼容 性是首要考慮的目標,否則就會破壞互聯網上無數現有的資產。因為必須要保持功能上的兼容,所以HTTP/2把HTTP分解成了“語義”和“語法”兩個部分,“語義”層不 做改動,與HTTP/1完全壹致(即RFC7231)。比如請求方法、URI、狀態碼、頭字段等概念都保留不變,這 樣就消除了再學習的成本,基於HTTP的上層應用也不需要做任何修改,可以無縫轉換到HTTP/2。特別要說的是,與HTTPS不同,HTTP/2沒有在URI裏引入新的協議名,仍用“http”表示明文協議, 用“https”表示加密協議。
首先,HTTP/2對報文的頭部做了壹個“大手術”。HTTP/1裏可以用頭字段“Content-Encoding”指定Body的編碼方式,比如用gzip壓縮來節約帶寬,但報文的另壹個組成部分?Header卻被無視了,沒有針對它的優化手段。
由於報文Header壹般會攜帶“User Agent”“Cookie”“Accept”“Server”等許多固定的頭字段,多達 幾百字節甚至上千字節,但Body卻經常只有幾十字節(比如GET請求、204/301/304響應),成了不折不扣 的“大頭兒子”。更要命的是,成千上萬的請求響應報文裏有很多字段值都是重復的,非常浪費,“?尾效 應”導致大量帶寬消耗在了這些冗余度極高的數據上。所以,HTTP/2把“ 頭部壓縮 ”作為性能改進的壹個重點,優化的方式妳也肯定能想到,還是“壓縮”。
不過HTTP/2並沒有使用傳統的壓縮算法,而是開發了專?的“ HPACK ”算法,在客戶端和服務器兩端建立“字典”, 用索引號表示重復的字符串 ,還釆用哈夫曼編碼來壓縮整數和字符串,可以 達到50%~90%的高壓縮率 。
妳可能已經很習慣於HTTP/1裏純文本形式的報文了,它的優點是“壹目了然”,用最簡單的工具就可以開 發調試,非常方便。但HTTP/2在這方面沒有“妥協”,決定改變延續了十多年的現狀,不再使用肉眼可?的ASCII碼,而是向下層的TCP/IP協議“靠攏”, 全面采用二進制格式 。這樣雖然對人不友好,但卻大大方便了計算機的解析。原來使用純文本的時候容易出現多義性,比如大小 寫、空白字符、回?換行、多字少字等等,程序在處理時必須用復雜的狀態機,效率低,還麻煩。
它把TCP協議的部分特性挪到了應用層,把原來的“Header+Body”的消息“打散”為數個小片的二進制“幀”(Frame),用“HEADERS”幀存放頭數據、“DATA”幀存放實體數據。這種做法有點像是“Chunked”分塊編碼的方式。也是“化整為零”的思路,但HTTP/2數 據分幀後“Header+Body”的報文結構就完全消失了,協議看到的只是壹個個的“碎片”。
消息的“碎片”到達目的地後應該怎麽組裝起來呢?HTTP/2為此定義了壹個“ 流”(Stream) 的概念,它是 二進制幀的雙向傳輸序列 ,同壹個消息往返的幀會分配壹個唯壹的 流ID 。妳可以想象把它成是壹個虛擬的“數據流”,在裏面流動的是壹串有先後順序的數據幀,這些數據幀按照次序組裝起來就是HTTP/1裏的請求報文和響應報文。
因為“流”是 虛擬 的,實際上並不存在,所以HTTP/2就可以在壹個TCP連接上 用“流”同時發送多個“碎片化”的消息 ,這就是常說的“ 多路復用 ”( Multiplexing)?多個往返通信都復用壹個連接來處理。在“流”的層面上看,消息是壹些有序的“幀”序列,而在“連接”的層面上看,消息卻是亂序收發 的“幀”。多個請求/響應之間沒有了順序關系,不需要排隊等待,也就不會再出現“隊頭阻塞”問題,降 低了延遲,大幅度提高了連接的利用率。
為了更好地利用連接,加大吞吐量,HTTP/2還添加了壹些 控制幀 來管理虛擬的“流”,實現了 優先級和流量控制 ,這些特性也和TCP協議非常相似。
HTTP/2還在壹定程度上改變了傳統的“請求-應答”工作模式,服務器不再是完全被動地響應請求,也可以 新建“流”主動向客戶端發送消息 。比如,在瀏覽器剛請求HTML的時候就提前把可能會用到的JS、CSS文 件發給客戶端,減少等待的延遲,這被稱為“ 服務器推送 ”(Server Push,也叫Cache Push)。
出於兼容的考慮,HTTP/2延續了HTTP/1的“明文”特點,可以像以前壹樣使用明文傳輸數據,不強制使用加密通信,不過格式還是二進制,只是不需要解密。但由於HTTPS已經是大勢所趨,而且主流的瀏覽器Chrome、Firefox等都公開宣布只支持加密的HTTP/2, 所以“事實上”的HTTP/2是加密的。也就是說, 互聯網上通常所能?到的HTTP/2都是使用“https”協議 名,跑在TLS上面 。為了區分“加密”和“明文”這兩個不同的版本,HTTP/2協議定義了兩個字符串標識符:“h2”表示加密的HTTP/2,“h2c”表示明文的HTTP/2,多出的那個字母“c”的意思是“clear text”。
在HTTP/2標準制定的時候(2015年)已經發現了很多SSL/TLS的弱點,而新的TLS1.3還未發布,所以加密 版本的HTTP/2在安全方面做了強化,要求下層的通信協議必須是TLS1.2以上,還要支持前向安全和SNI,並 且把幾百個弱密碼套件列入了“黑名單”,比如DES、RC4、CBC、SHA-1都不能在HTTP/2裏使用,相當於 底層用的是“TLS1.25”。