參考
HTTP發展史
- HTTP/0.9 - 單行協議
- 問世于1990年,那時的HTTP非常簡單: 只支持GET方法; 沒有首部; 只能獲取純文本
- HTTP/1.0 - 搭建協議的框架
- 1996年,HTTP正式被作為標準公布,版本為HTTP/1.0。1.0版本增加了首部、狀態碼、權限、緩存、長連接(默認短連接)等規范,可以說搭建了協議的基本框架。
- HTTP/1.1 - 進一步完善
- 1997年,1.1版本接踵而至。1.1版本的重大改進在于默認長連接; 強制客戶提供Host首部;管線化;Cache-Control、ETag等緩存的相關擴展
- 注: Etag和Last-Modified同時存在,以Etag為主
- 1997年,1.1版本接踵而至。1.1版本的重大改進在于默認長連接; 強制客戶提供Host首部;管線化;Cache-Control、ETag等緩存的相關擴展
【HTTP/1.0的缺陷】:
- 連接無法復用: 一個連接對應一次握手
- 隊頭阻塞: 前面一個連接未完成,后面的連接無法進行
對于問題1, HTTP/1.1新增了一個connection: keep-alive
,使連接完成后不斷開.
目前存在的問題
? 我們先來看看HTTP發展到1.1存在的問題:
- 線頭阻塞: TCP連接上只能發送一個請求,前面的請求未完成前,后續的請求都在排隊等待.
- 多個TCP連接:
- 雖然HTTP/1.1管線化可以支持請求并發,但是瀏覽器很難實現,chrome、firefox等都禁用了管線化.所以1.1版本請求并發依賴于多個TCP連接,建立TCP連接成本很高,還回存在慢啟動的問題.
- 頭部冗余,采用文本格式
- HTTP/1.X版本是采用文本格式,首部未壓縮,而且每一個請求都會帶上cookie、user-agent等完全相同的首部
- 客戶端需要主動請求
HTTP/2.0中的一些重大改進
HTTP2性能提升的核心就在于二進制分幀層。HTTP2是二進制協議,他采用二進制格式傳輸數據而不是HTTP/1.x的文本格式
-
1.1響應是文本格式,而2.0把響應劃分為兩個幀
- HEADERS frame: 首部
- DATA frame: 消息負載
-
也就是說: 一條HTTP響應,劃分為兩個幀來傳輸,并且采用二進制來編碼
- 流(Stream): 已經建立TCP連接上的雙向字節流,可以承載一個或多個消息
- 消息(Message): 一個完整的HTTP請求或響應,由一個或多個幀組成。特定消息的幀在同一個流上發送,這意味著一個HTTP請求或響應只能在一個流上發送.
- 幀(Frame): 通信的基本單位。 一個TCP連接上可以由任意數量的流
多路復用
HTTP/2.0讓所有的通信都在一個TCP連接上完成,真正實現了請求的并發.
HTTP/2.0建立一個TCP連接,一個連接上面可以有任意多個流(stream),消息分割成一個或多個幀在流里面傳輸。幀傳輸過去以后,再進行重組,形成一個完整的請求或響應。這使得所有的請求或響應都無法阻塞。
頭部壓縮
在1.X版本中,首部用文本格式傳輸,通常會給每個傳輸增加500~800字節的開銷。大多數請求的首部字段是相同的(如cookie、user-agent等)。
HTTP2為此采用HPACK壓縮格式來壓縮首部,頭部壓縮需要在瀏覽器和服務器之間:
- 維護一份相同的靜態字典,包含常見的頭部名稱,以及常見的頭部名稱和值的組合
- 維護一份相同的動態字典,可以動態的添加內容
- 通過靜態Huffman編碼對傳輸的首部字段進行編碼
HTTP/2.0的靜態字典,部分:
Index | Header Name | Header Value |
---|---|---|
1 | :authority | |
2 | :method | GET |
3 | :method | POST |
4 | :path | / |
5 | :path | /index.html |
6 | :schema | http |
7 | :schema | https |
8 | :status | 200 |
9 | :status | 204 |
所以我們在傳輸首部字段的時候,例如要傳輸method:GET
,那我們只需要傳輸靜態字典里面method: GET
對應的索引值就可以了,一個字節搞定.
像user-agent、cookie
這種字典里面只有首部名稱而沒有值的首部,第一次傳輸需要user-agent
在靜態字典中的索引以及他的值,值會采用Huffman編碼來減小體積
第一次傳輸過user-agent
之后,瀏覽器和服務器就會把它添加到自己的動態字典中。后續傳輸就可以傳輸索引了,一個字節
服務器推送技術
-
服務器推送: 使得服務器可以預測客戶端需要的資源,主動推送到客戶端
-
例如: 客戶端請求index.html,服務器端能夠額外推送
script.js
和style.css
.原理:- 客戶端發送請求時,服務器能夠分析這個頁面所依賴的其他資源,主動推送到客戶端的緩存
- 當客戶端收到原始網頁的請求時,它需要的資源已經位于緩存