之前整理了一遍http1.0, http1.1, http2.0之前的區(qū)別趟咆,但是里面很多細節(jié)都沒有弄清值纱。特別是在http1.1和2.0之間關于多路復用虐唠,頭壓縮這一塊兒。 最近在外網(wǎng)上搜到一遍蠻詳細的文章咱筛,覺得講的很清晰,所以就翻譯了分享給大家杆故。原文地址
背景
在比較http2 和http1.1區(qū)別之前,讓我們先宏觀的看一看兩者歷史性的發(fā)展处铛。
HTTP1.1
1989年作為萬維網(wǎng)交流標準,屬于應用層協(xié)議撤蟆,在客戶端和服務器端進行信息交換奕塑。這個過程中家肯,客戶端發(fā)送一個基于文本的請求到服務器通過調(diào)用GET 或者POST方法龄砰。 相應的,服務器返回資源給客戶端息楔。
例如:
GET /index.html HTTP/1.1
Host: www.example.com
該請求用GET方法。 服務器會返回一個HTML頁面和一些圖片值依,樣式表和一些其他資源愿险。注意:所有的資源并不是一次性返回給客戶端辆亏。兩者會在之間反反復復進行幾次請求和響應扮叨,直到該html頁面所有的資源內(nèi)容在你的屏幕上被繪制缤弦。
HTTP/2
http2 剛開始為SPDY協(xié)議狸捅,起初Google為了減少加載延遲而開發(fā)的,通過使用例如壓縮累提,多路復用尘喝,優(yōu)化等。 目前該協(xié)議已經(jīng)被很多瀏覽器所支持斋陪。
從技術角度而言朽褪,http1.1和2.0 最大的區(qū)別是二進制框架層。與 http1.1把所有請求和響應作為純文本不同,http2 使用二進制框架層把所有消息封裝成二進制,且仍然保持http語法屑咳,消息的轉換讓http2能夠嘗試http1.1所不能的傳輸方式盏浇。
Http1.1 流水線和隊頭阻塞
客戶端首次接受的響應常常不能完全渲染。相反,它包含一些其他需要的資源。 因此,客戶端必須發(fā)出一些其他請求梁棠。 Http1.0客戶端的每一個請求必須重新連接,這是非常耗時和資源的斗埂。
Http1.1 通過引入長連接和流水線技術處理了這個問題符糊。 通過長連接,http1.1假定這個tcp連接應該一直打開直到被通知關閉呛凶。 這就允許客戶端通過同一連接發(fā)送多個請求男娄。不巧的是,這優(yōu)化策略有個瓶頸漾稀。當一個隊頭的請求不能收到響應的資源模闲,它將會阻塞后面的請求。這就是知名的隊頭阻塞問題崭捍。雖然添加并行的tcp連接能夠減輕這個問題尸折,但是tcp連接的數(shù)量是有限的,且每個新的連接需要額外的資源殷蛇。
Http2 二進制框架層的優(yōu)勢
在http2 实夹, 二進制框架層編碼 請求和響應 并把它們分成更小的包,能顯著的提高傳輸?shù)撵`活性粒梦。
與http1.1利用多個tcp連接來減少隊頭阻塞的影響相反亮航,http2在兩端建立一個單獨的連接。該連接包含多個數(shù)據(jù)流匀们。 每個流包含多個請求/響應格式的消息 缴淋。 最終,每個消息被劃分為更小的幀單元。
在最細微層面上宴猾,交流通道由一系列二進制幀組成圆存,每一個被標記到特定的流叼旋〕鸲撸可識別標簽允許連接在傳輸過程中來交錯這些幀并在另一端去組合它們。 交錯的請求和響應能夠并行的傳輸而不被阻塞夫植。該過程被稱作多路復用技術讹剔。
因為多路復用允許客戶端并行的構建多個流,這些流僅僅需要一個tcp連接详民。 相比http1.1能很大程度上減少內(nèi)存和整個網(wǎng)絡中的足跡延欠。所以有更好的網(wǎng)絡及帶寬利用率。
Tcp連接也能改善https協(xié)議的性能沈跨,因為客戶端可針對多個請求/響應 復用同一個連接 在tls和ssl握手期間由捎,雙方在整個會話同意使用唯一的key。 如果連接中斷饿凛,新的會話需要一個新生成的key狞玛。 因此,維持單鏈接能很大程度優(yōu)化https涧窒。
Http2 流的優(yōu)先級
流優(yōu)先級不僅僅解決同一資源的競態(tài)問題心肪,也允許開發(fā)人員自定義請求的權重。
如你所知纠吴,二進制框架層把消息組織成并行數(shù)據(jù)流硬鞍。 當一個客戶端發(fā)送并行請求,它能把請求的響應設置優(yōu)先級權重 戴已,從1-256 固该,更高的數(shù)字代表更高的優(yōu)先級。 此外糖儡,該客戶端也通過特定的流ID指明每個流的依賴伐坏。如果id被忽略,說明這個流是根流休玩。
上圖中著淆,channel包含6個流,每個有一個唯一id 且有一個特定的權重拴疤。 流1沒有父ID永部,說明是根節(jié)點。分配給每個流的資源將根據(jù)權重和它們需要的依賴呐矾。
服務器端利用該信息創(chuàng)建一個依賴樹苔埋,通過次樹來決定響應的數(shù)據(jù)。根據(jù)之前的圖表蜒犯,依賴樹如下:
根據(jù)此依賴樹组橄,所有可用資源將會先分配給 流1荞膘。 因為流2依賴流1,流2直到流1完成后才處理玉工。流2完成后羽资,資源分配給流3,流4. 兩者權重比為2:4遵班,資源也會依此來分配屠升。3,4完成后,流5狭郑,流6將會等分資源腹暖。
作為開發(fā)者,你可以根據(jù)需要去設置權重翰萨,例如脏答,給高分辨率圖片設置低優(yōu)先級。Http2協(xié)議允許客戶端在運行時根據(jù)用戶交互重新分配權重和改變依賴亩鬼。 然而殖告,服務器端會改變優(yōu)先級根據(jù)如果某個流因為請求特定資源被阻塞。
緩沖區(qū)溢出
客戶端和服務器都有一定數(shù)量的緩沖區(qū)來持有還未被處理的請求辛孵。
當服務器返回給客戶端一大堆數(shù)據(jù)丛肮,或者客戶端上傳一個大的圖片和視頻,可能造成緩沖區(qū)溢出魄缚。
為了避免緩沖區(qū)溢出宝与,流控制機制可以禁止發(fā)送者發(fā)送太多數(shù)據(jù)。下面我們聊聊http1.1和http2不同的流控制機制冶匹。
Http1.1
http1.1流控制基于tcp連接习劫。當連接建立時,兩端通過系統(tǒng)默認機制建立緩沖區(qū)嚼隘。 并通過ack報文來通知對方接收窗口大小诽里。
因為Http1.1 依靠傳輸層來避免流溢出,每個tcp連接需要一個獨立的流控制機制飞蛹。
Http2
http2通過一個連接來多路復用谤狡。 結果是在傳輸層的tcp連接不足以管理每個流的發(fā)送。http2允許客戶端和服務器端實現(xiàn)他們自己的流控制機制卧檐,而不是依賴傳輸層墓懂。兩端在傳輸層交換可用的緩沖區(qū)大小,來讓他們在多路復用流上設置自己的接收窗口霉囚。
預測資源請求
通常web應用捕仔,客戶端發(fā)送一個GET請求且收到一個HTML。當檢測收到html的內(nèi)容,會發(fā)現(xiàn)它需要拿取其他的資源榜跌。例如CSS和JS文件闪唆。然后就會繼續(xù)請求其他資源。這些請求會最終加長連接加載時間钓葫。
解決辦法:因為服務器端提前知道客戶端需要額外資源悄蕾,服務器端可以通過提前發(fā)送這些資源給客戶來節(jié)省時間,而不用客戶來請求瓤逼。
Http/1.1 資源內(nèi)聯(lián)
如果開發(fā)者提前知道客戶機器需要哪些額外的資源來渲染界面笼吟,他們使用資源內(nèi)聯(lián)的技術來包含需要的資源。例如:如果一個客戶需要一個特定的CSS文件霸旗,內(nèi)聯(lián)該文件就可以不通過請求來拿到,減少客戶端必須發(fā)送的請求數(shù)戚揭。
該技術對于小文件是可行的诱告,但是大文件會降低連接的速度。還可能造成文件多次請求民晒。
Http2 服務器推送
因為http2支持多個并發(fā)響應精居,服務器可以提前把HTML 頁面中的其他資源在客戶端請求之前發(fā)給它。
服務器先發(fā)送一個PUSH_PROMISE 幀通知客戶端將推送資源潜必。該幀只包含頭消息靴姿,且允許用戶提前知道哪些資源將會推送。如果客戶端已經(jīng)緩存磁滚,可以拒絕該推送佛吓。
壓縮技術
常用的優(yōu)化web應用是用壓縮算法減少HTTP消息大小。 HTTP/1.1 和2 都用該技術HTTP/1.1不支持整個消息壓縮垂攘。下面我們來聊聊區(qū)別维雇。
Http1.1
Gzip已經(jīng)被用于壓縮http消息很久了,特別是減少CSS和JS腳本的文件晒他。然而消息頭部分依然是純文本發(fā)送吱型。盡管每個頭都很小,但隨著請求越來越多陨仅,連接的負擔就會越重津滞,如果帶了cookie. Header將變得更大。
Http2
Http2 的二進制框架層在細節(jié)上表現(xiàn)出強大的控制力灼伤,在頭壓縮上也是如此触徐。 http2 能把頭從他們的數(shù)據(jù)中分離,并封城頭幀和數(shù)據(jù)幀饺蔑。 http2特定的壓縮程序HPACK可以壓縮頭幀锌介。 該算法用Huffman編碼頭metadata,可以很大程度上減少頭大小。此外孔祸, HPACK可以跟蹤先前傳輸?shù)膍etadata字段隆敢,然后通過動態(tài)改變服務器端和客戶端共享的索引來進一步壓縮。如下:
如上圖崔慧,上述字段只有path有不同的值拂蝎。 因此,HPACK可以只發(fā)送需要改變的值
此外:
關于Https,Http1.0, 1.1, 2.0的區(qū)別惶室,可以參考這篇文章
關于tcp,udp報文講解和分析温自,可以參考這里
關于tcp,udp 三次握手和四次揮手,可以參考這里