目錄:
- http1.1 長連接
- HTTP 1.1支持只發送header信息(不帶任何body信息)
- http1.1 host請求頭
- HTTP2.0使用多路復用技術(Multiplexing)
- HTTP/2新增首部壓縮(Header Compression):采用HPACK算法
- HTTP/2新增服務端推送(Header Compression)
參考的文章:
http1.1 長連接
HTTP1.1默認使用長連接,可有效減少TCP的三次握手開銷。
HTTP 1.0規定瀏覽器與服務器只保持短暫的連接,瀏覽器的每次請求都需要與服務器建立一個TCP連接,服務器完成請求處理后立即斷開TCP連接
當一個網頁文件中包含了很多圖像的地址的時候,那就需要很多次的http請求和響應,每次請求和響應都需要一個單獨的連接,每次連接只是傳輸一個文檔和圖像,上一次和下一次請求完全分離。即使圖像文件都很小,但是客戶端和服務器端每次建立和關閉連接卻是一個相對比較費時的過程,並且會嚴重影響客戶機和服務器的性能。當一個網頁文件中包含JavaScript文件,CSS文件等內容時,也會出現類似上述的情況。
為了克服HTTP 1.0的這個缺陷,HTTP 1.1支持持久連接(HTTP/1.1的默認模式使用帶流水線的持久連接),在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲。一個包含有許多圖像的網頁文件的多個請求和應答可以在一個連接中傳輸,但每個單獨的網頁文件的請求和應答仍然需要使用各自的連接。
HTTP 1.1還允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但服務器端必須按照接收到客戶端請求的先后順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容,這樣也顯著地減少了整個下載過程所需要的時間。
通過請求頭中connection字段在表明是否支持長鏈接
在http1.1中,client和server都是默認對方支持長鏈接的(即connection的值默認我Keep-Alive), 如果client使用http1.1協議,但又不希望使用長鏈接,則需要在header中指明connection的值為closer(connection默認為Keep-Alive);如果server方也不想支持長鏈接,則在response中也需要明確說明connection的值為closer。不論request還是response的header中包含了值為closer的connection,都表明當前正在使用的tcp鏈接在當天請求處理完畢后會被斷掉。以后client再進行新的請求時就必須創建新的tcp鏈接了。
HTTP 1.1支持只發送header信息(不帶任何body信息)
如果服務器認為客戶端有權限請求服務器,則返回100,否則返回401。客戶端如果接受到100,才開始把請求body發送到服務器。這樣當服務器返回401的時候,客戶端就可以不用發送請求body了,節約了帶寬。另外HTTP還支持傳送內容的一部分。這樣當客戶端已經有一部分的資源后,只需要跟服務器請求另外的部分資源即可。這是支持文件斷點續傳的基礎。
RANGE:bytes是HTTP/1.1新增內容,HTTP/1.0每次傳送文件都是從文件頭開始,即0字節處開始。RANGE:bytes=XXXX表示要求服務器從文件XXXX字節處開始傳送,這就是我們平時所說的斷點續傳!
http1.1 host請求頭
HTTP1.0是沒有host域的,HTTP1.1才支持這個參數。
1.0中WEB瀏覽器無法使用主機頭名來明確表示要訪問服務器上的哪個WEB站點,這樣就無法使用WEB服務器在同一個IP地址和端口號上配置多個虛擬WEB站點。在HTTP 1.1中增加Host請求頭字段后,WEB瀏覽器可以使用主機頭名來明確表示要訪問服務器上的哪個WEB站點,這才實現了在一台WEB服務器上可以在同一個IP地址和端口號上使用不同的主機名來創建多個虛擬WEB站點。
HTTP 1.1還提供了與身份認證、狀態管理和Cache緩存等機制相關的請求頭和響應頭。
HTTP2.0使用多路復用技術(Multiplexing)
多路復用允許同時通過單一的 HTTP/2 連接發起多重的請求-響應消息。
"HTTP1.1在同一時間對於同一個域名的請求數量有限制,超過限制就會阻塞請求"。多路復用底層采用增加二進制分幀層的方法,使得不改變原來的語義、首部字段的情況下提高傳輸性能,降低延遲。
二進制分幀將所有傳輸信息分割為更小的幀,用二進制進行編碼,多個請求都在同一個TCP連接上完成,可以承載任意數量的雙向數據流。HTTP/2更有效的使用TCP連接,得到性能上的提升。
二進制分幀層把數據轉換為二進制的同時,也把數據分成了一個一個的幀。幀是HTTP/2中數據傳輸的最小單位;每個幀都有
在一個TCP鏈接中,可以同時雙向地發送幀,而且不同流中的幀可以交錯發送,不需要等某個流發送完,才發送下一個。也就是說在一個TCP連接中,可以同時傳輸多個流,即可以同時傳輸多個HTTP請求和響應,這種同時傳輸不需要遵循先入先出等規定,因此也不會產生阻塞,效率極高。stream_ID
字段,表示這個幀屬於哪個流,接收方把stream_ID
相同的所有幀組合到一起就是被傳輸的內容了。而流是HTTP/2中的一個邏輯上的概念,它代表着HTTP/1.1中的一個請求或者一個響應,協議規定client發給server的流的stream_ID
為奇數,server發給client的流ID是偶數。需要注意的是,流只是一個邏輯概念,便於理解和記憶的,實際並不存在。
HTTP/2新增首部壓縮(Server Push):采用HPACK算法
在 HTTP/1 中,HTTP 請求和響應都是由「狀態行、請求 / 響應頭部、消息主體」三部分組成。一般而言,消息主體都會經過 gzip 壓縮,或者本身傳輸的就是壓縮過后的二進制文件(例如圖片、音頻),但狀態行和頭部卻沒有經過任何壓縮,直接以純文本傳輸。
隨着 Web 功能越來越復雜,每個頁面產生的請求數也越來越多,根據 HTTP Archive 的統計,當前平均每個頁面都會產生上百個請求。越來越多的請求導致消耗在頭部的流量越來越多,尤其是每次都要傳輸 UserAgent、Cookie 這類不會頻繁變動的內容,完全是一種浪費。
Hapck原理:
具體規則可以描述為:
- 通信雙方共同維護了一份靜態表,包含了常見的頭部名稱與值的組合
- 根據先入先出的原則,維護一份可動態添加內容的動態表
- 用基於該靜態哈夫曼碼表的哈夫曼編碼數據
當要發送一個請求時,會先將其頭部和靜態表對照,對於完全匹配的鍵值對,可以直接使用一個數字表示,如method: GET,對於頭部名稱匹配的鍵值對,可以將名稱使用一個數字傳輸,同時告訴服務端將它添加到動態表中,以后的相同鍵值對就用一個數字表示了。這樣,像cookie這些不經常變動的值,只用發送一次就好了。
HTTP/2新增服務端推送(Header Compression)
即服務器發送/user.html
時,就可以主動把/user.js
和style.css
push給瀏覽器,使資源提前達到瀏覽器;除了靜態文件,還可以推送比較耗時的API,只是需要提前將參數和cookie等信息通過某個方式告知服務端(如和路由關聯)。Apache、GO的net/http、node-spdy都實現了server push(但ngnix沒有=_=)
Server push是HTTP/2協議里面唯一一個需要開發者自己配置的功能。其他功能都是服務器和瀏覽器自動實現,無需開發者介入。
在HTTP1.1時代,也有提前獲取資源的方法,如preload和prefetch,前者是在頁面解析初期就告訴瀏覽器,這個資源是瀏覽器馬上要用到的,可以立刻發送對資源的請求,當需要用到該資源時就可以直接用而不用等待請求和響應的返回了;后者是當前頁面用不到但下一頁面可能會用到的資源,優先級較低,只有當瀏覽器空閑時才會請求prefetch標記的資源。從應用層面上看,preload和server push並沒有什么區別,但是server push減少瀏覽器請求的時間,略優於preload,在一些場景中,可以將兩者結合使用。