超文本傳輸協定(英文:hypertext transfer protocol,縮寫:http)是網際網路上應用最為廣泛的一種網絡協定。設計 http 最初的目的是為了提供一種釋出和接收 html 頁面的方法。通過 http 或者 https 協定請求的資源由統一資源辨別符(uri)來辨別。
雖然http/1.1穩定運作了十多年了,但http/2來勢洶洶,作為技術工程師有必要學習一下http/2。今天,阿裡雲cdn安防技術專家金九将從曆史、特性、調試、性能四個層面,來全面解析http/2,希望本文可以給你帶來一些啟發。
1、 http/0.9
最早的原型,1991年釋出,該版本極其簡單,隻支援 get 方法,不支援 mime 類型和各種 http 首部等等。
2、 http/1.0
1996年釋出。http/1.0在http/0.9的基礎之上添加很多方法,各種 http 首部,以及對多媒體對象的處理。
除了get指令,還引入了post指令和head指令,豐富了浏覽器與伺服器的互動手段。
任何格式的内容都可以發送。這使得網際網路不僅可以傳輸文字,還能傳輸圖像、視訊、二進制檔案。這為網際網路的大發展奠定了基礎。
http請求和回應的格式也變了。除了資料部分,每次通信都必須包括頭資訊(http header),用來描述一些中繼資料。
可以說,http/1.0是對http/0.9做了革命性的改變,但http/1.0依然有一些缺點,其主要缺點是每個tcp連接配接隻能發送一個請求,發送資料完畢後連接配接就關閉,如果還要請求其他資源,就得再建立一個連接配接。雖然有些浏覽器為了解決這個問題,用了一個非标準的connection頭部,但這個不是标準頭部,各個浏覽器和伺服器實作有可能不一緻,是以不是根本解決辦法。
3 、http/1.1
1999年正式釋出。http/1.1是目前主流的 http 協定。完善了之前 http 設計中的結構性缺陷,明确了語義,添加和删除了一些特性,支援更加複雜的的 web 應用。
經過了十多年将近20年的發展,這個版本的http協定已經很穩定了,跟http/1.0相比,它新增了很多引人注目的新特性,比如host協定頭、range分段請求、預設持久連接配接、壓縮、分塊傳輸編碼(chunked)、緩存處理等等,至今都大量使用,而且很多軟體依賴這些特性。
雖然http/1.1并不像http/1.0對于http/0.9那樣的革命性,但是也有很多增強,目前主流浏覽器均預設采用http/1.1。
# 4、spdy
spdy(發音:speedy)協定由google開發,主要解決 http/1.1 效率不高的問題,于2009年公開,到2016年初結束使命。因為http/2已經被ietf标準化了,以後各種新版浏覽器都會支援http/2,google認為spdy已經沒有存在的必要了,接下來的使命由http/2去完成。
5、http/2
http/2是最新的http協定,已于2015年5月份正式釋出, chrome、 ie11、safari以及firefox 等主流浏覽器已經支援 http/2協定。
注意是http/2而不是http/2.0,這是因為ietf(internet engineering task force,網際網路工程任務組)認為http/2已經很成熟了,沒有必要再釋出子版本了,以後要是有重大改動就直接釋出http/3。
其實,http/2的前身是spdy,甚至它倆的目标、原理和基本實作都差不多。ietf組委會中有很多google工程師,将spdy推動成為标準也就不足為奇了。
http/2不僅優化了性能而且相容了http/1.1的語義,其幾大特性與spdy差不多,與http/1.1有巨大差別,比如它不是文本協定而是二進制協定,而且http頭部采用hpack進行壓縮,支援多路複用、伺服器推送等等。
1、二進制協定
length (24)
type (8)
flags (8)
r
stream identifier (31)
+=+=============================================================+
之是以說是基本格式,是因為所有http/2 frame都是由該基本格式來封裝,類似于tcp頭,目前有10個frame,由type字段來區分,各個frame都有自己的二進制格式,都封裝frame payload中。
其中有兩個重要的frame:headers frame(type=0x1)和data frame(type=0x0),分别對應http/1.1中的消息頭(header)和消息體(body),由此可見語義并沒有太大變化,而是文本格式變成二進制的frame。二者的轉換和關系如下圖(摘自 《high performance browser networking》):
此外,http/2中還有流(stream)和消息(message)的概念,通過stream identifier(即流id)字段來辨別,流id一樣的是同一個流,流中包含消息,這個消息對應http/1.x的請求消息(request message)或者響應消息(response message),消息是通過幀(frame)來傳輸的,響應消息比較大,可能由多個data frame來傳輸。http/2中流、消息和幀的對應關系如下圖(摘自 《high performance browser networking》):
2、頭部壓縮
http/1.x 每次請求和響應,都會攜帶大量備援消息頭資訊,比如cookie和user agent,基本一樣的内容,每次請求浏覽器都會預設攜帶,這會浪費很多帶寬資源,也影響了速度。這是因為http是無狀态協定,每次請求都必須附上所有資訊,進而導緻了每次請求都帶上大量重複的消息頭。
為此,http/2做了優化,對消息頭采用hpack格式進行壓縮傳輸,并對消息頭建立索引表,相同的消息頭隻發送索引号,進而提高效率和速度。但付出的代價是用戶端和伺服器均維護一個索引表,在如今記憶體不值錢的時代,這點空間換取時間還是非常值得的。
3、多路複用
多路複用是指在一個tcp連接配接裡,用戶端和伺服器都可以同時發送多個請求或者響應,對http/1.x來說各個請求和響應都是有嚴格的次序要求,而在http/2中,不用按照次序一一對應,而且并發的多個請求或者響應中任何一個請求阻塞了不會影響其他的請求或者響應,這樣就避免了“隊頭堵塞”。如下圖(摘自 《high performance browser networking》):
4、伺服器推送
伺服器推送(server push)是指在http/2中伺服器未經請求可以主動給用戶端推送資源。例如服務端可以主動把 圖檔、js 和 css 檔案推送給浏覽器,而不需要浏覽器解析html後再發送這些請求。當浏覽器解析html後這些需要的資源都已經在浏覽器裡了,大大提高了網頁加載的速度。如下圖(摘自 《high performance browser networking》):
浏覽器發起請求page.html這個頁面,這個頁面中引用了script.js和style.css,伺服器在響應page.html後順便推送了script.js和style.css這兩個檔案,這樣浏覽器解析完page.html後發現引用的script.js和style.css已經在本地了,不需要再發送請求了,這樣就節省了兩次請求和這兩次請求所花的網絡時間,大大提高了網絡性能和使用者體驗。
5、安全
http的安全是由ssl/tls來保障,也就是https,其實http/2并不強制要求依賴ssl/tls,但是,目前主流浏覽器均隻支援基于ssl/tls的http/2,況且在網絡劫持日益猖獗的網際網路環境下,https将是未來的趨勢,http/2基于https也是未來的趨勢,而各大主流浏覽器在實作http/2之初均隻支援ssl/tls的http/2,可見安全也是http/2的重要特性之一。
從原理和目标上看http/2和spdy差不多,從nginx官方代碼上看http/2和spdy的實作也差不多。nginx官方代碼中已經删除了spdy子產品的代碼,取而代之的是http2子產品(ngx_http_v2_module)。
1、啟用
1.1、在編譯參數中加入http2子產品(預設已經有ssl子產品了):
1.2、生成測試證書和私鑰
1.3、配置http2
1.4、啟動tengine即可:
用chrome浏覽器測試:
2、抓包分析
從抓包來學習http/2格式是最好的辦法,但http/2又是基于https的,也就是加密的,直接抓包看到的是密文,沒有意義,還好wireshark提供解密https流量的辦法可以比較友善地調試http/2。
2.1、先導出系統變量$sslkeylogfile,以osx系統為例
2.2、打開chrome或者firefox
然後看看檔案~/ssl_debug/ssl_pms.log有沒有内容,有内容就可以用wireshark解密https資料了。
2.3、wireshark設定
啟動抓包:
測試機器配置:cache1.cn1, 115.238.23.13, 16核intel(r) xeon(r) cpu l5630 @ 2.13ghz,48g記憶體,萬兆網卡
測試工具:h2load
測試結果:
1、無論是否keepalive,http/2與spdy/3.1性能相當,http/2略優。
2、在size為1k、2k、4k測試結果中保持較低rt情況下qps也較高,cpu沒有達到瓶頸,加大壓測用戶端數量後qps有所提高,但rt變大,5xx也變多(這部分資料沒有給出,是測試時記錄的現象)。
在size為16k、32k、64k、128k、256k的測試結果中cpu達到瓶頸,随着size變大,qps降低,rt變高,cpu性能消耗較多的函數是gcm_ghash_clmul。
在size為512k時網卡達到瓶頸,cpu沒有達到瓶頸。
3、在開啟keepalive的情況下,http/1.1的性能與http/2的性能差距不是很大。但關閉keepalive時http/2的性能比http/1.1更好。
相比之前的傳輸協定,http/2在底層方面做了很多優化。有安全、省時、簡化開發、更好的适應複雜頁面、提供緩存使用率等顯著的優勢,各大公司也已經紛紛開始使用http/2協定了。阿裡雲早在去年釋出的cdn6.0服務就已正式支援http/2,通路速度最高可提升68%。不知不覺中,一個更安全、更可靠、更高速的時代已經悄然而至。