1. HTTP/2 的幀與流等概念
HTTP/2 是基於二進制幀(Frame),他將一個TCP連接分爲若干個流(Stream),每個流中可以傳輸若干消息(Message),每個消息由若干最小的二進制幀(Frame)組成。
科普:什麼是二進制?如果一個二進制人類看得懂,那他就是字符串,否則就是二進制
-------------------
| Length | Type |
-------------------
| Flag | StreamID |
-------------------
| Payload |
-------------------
前面九個字節代表 Length (長度)、Type (類型)、Flags (標記位)、StreamID (所在流的 ID),第五部分 Payload (數據),一般爲16 K - 16 M(這裏說的數據不只是請求體,包含了從 HTTP 請求頭開始的所有)
與 HTTP/1.* 的區別
GET
- 這裏假設是一個 Frame,前面這個框代表前九個字節
- header 代表這是請求頭
- + (true) 號代表當前這部分結束
- 冒號開頭的表示僞頭,h2 現在用這三行表示爲以前的請求頭第一部分
- 以前的冒號變成了等於號(因爲冒號被佔用了)
- 大寫變成了小寫,不允許小寫
POST
- 至少三個 Frame
- 第一個 Frame,- END_STREAM 表示請求沒有結束,- END_HEADERS 表示請求頭也沒有結束
- 第二個 Frame,COUTINUATION 表示這是一個繼續,要和前面一個一起看,+ END_HEADERS 到我這一幀,請求頭結束了
- 以前請求的第三部分(回車),到 h2 就不需要了,刪除了
- DATA 數據,+ END_STREAM 代表請求到這裏都結束了
響應
總結
基本沒什麼區別,只不過是吧以前一個請求、一個響應變成了不同的幀,讓那九個字節關聯起所有的幀,還有僞頭的概念
2. HTTP/2的流與多路複用
- 上次說到 HTTP/1.1 管道的概念,之所以不能使用就是因爲響應的時候必須要按順序
- 但是在 HTTP/2 中就沒有這個問題了,他每個響應都會告訴你對應的是哪個,因爲他有前面 9 個字節可以做標記,所以在管道中每個請求響應都是獨立的,大大的提升了效率
- 但是 H2 並不僅僅是加了標記,由於順序是亂的,所以請求方需要去做一個整合,響應方 Frame 太多了請求方一般還一般需要壓縮在發送
- 有了多路複用以後,以前的並行方案就沒有必要了,並行的話還要多開好幾個連接
- 一個管道中能開多少個“路”呢?答案是 100 可以, 1000 個也可以,一般來說 100 都算少的,所以他的效率是極高的
3. HTTP/2 的 Server Push 的利與弊
先說結論,我們實際生活中並不會或者說很少使用到這個功能
- 首先客戶端還是需要先發送第一個請求
- 但是此時服務器會主動多返回一些東西回來
- 當客戶端再需要請求這些文件的時候,就會發現已經有了,就不再請求了
那麼問題來了,服務器怎麼知道客戶端需要哪些東西呢?
答案是程序員認爲去提前寫好的
配置 Server Push
方法一:Nginx
// Nginx
location {
root /usr/share/nginx*html
index index.html index.htm
http2_push /style.css
http2_push /example.css
}
方法二:Nginx 和 響應頭
// Nginx
location = / {
...
http2_push_preload on
}
// index.html 響應頭
Link: </style.css>; rel=preload; as=style
- 一般這樣的配置非常繁瑣,如果文件名稱變動,還需要後臺配合來改配置,一般沒人會這麼做
- 還有現在的前端都是工程化了,文件名一般都是混合了哈希,後端根本不知道文件名
- 所以幾乎沒有人用
- 當然 Server Push 很好,可以提前響應,但是現實狀況是後臺不知道提前去響應什麼