HTTP是應用層協議,是基於TCP底層協議而來。
TCP的機制限定,每建立一個連接需要3次握手,斷開連接則需要4次揮手。
HTTP協議採用“請求-應答”模式,HTTP1.0下,HTTP1.1非Keep-Alive模式下,每個請求都要新建一個連接,完成之後立即斷開連接。如果有新的請求,則要重新創建請求連接(HTTP協議為無連接的協議)。
這樣不免造成了網絡傳輸數據一定的延遲,1999年推出HTTP1.1,雖然可以通過設置延遲時間,讓連接延遲關閉。但仍然有線頭阻塞,max-connection最大連接限制了並行請求數量等痛點,難以應對日益增長的大數據實時傳輸。
新一代HTTP2.0協議應運而生,提高HTTP應對高併發場景下的數據傳輸能力。
雜談:HTTP1.1 與 HTTP2.0 知多少?
「 HTTP1.1」
Pipelining管道化
提出管道化方案解決連接延遲,服務端可設置Keep-Alive來讓連接延遲關閉時間,但因為瀏覽器自身的Max-Connection最大連接限制,同一個域名 (host) 下的請求連接限制(同域下谷歌瀏覽器是一次限制最多6個連接),只能通過多開域名來實現,這也就是我們的靜態資源選擇放到CDN上或其它域名下,來提高資源加載速度。
pipelining方案需要前後端支持,但絕大部分的HTTP代理器對pipelining的支持並不友好。
只支持GET/HEAD
pipelining只支持GET/HEAD方式傳送數據,不支持POST等其它方式傳輸。
頭部信息冗餘
HTTP是無狀態的,客戶端/服務端只能通過HEAD的數據維護獲取狀態信息,這樣就造成每次連接請求時都會攜帶大量冗餘的頭部信息,頭部信息包括COOKIE信息等。
超文本協議
HTTP1.X是超文本協議傳輸。超文本協議傳輸,發送請求時會找出數據的開頭和結尾幀的位置,並去除多餘空格,選擇最優方式傳輸。如果使用了HTTPS,那麼還會對數據進行加密處理,一定程度上會造成傳輸速度上的損耗。
線頭阻塞
pipelining通過延遲連接關閉的方案,雖然可同時發起對服務端的多個請求,但服務端的response依舊遵循FIFO(first in first out)規則 依次返回。
舉個例子客戶端發送了1、2、3、4四個請求,如果1沒返回給客戶端,那麼2,3,4也不會返回。這就是所謂的線頭阻塞。高併發高延遲的場景下阻塞明顯。
HTTP1.X傳輸優化方法
- 多個資源合併成一個請求連接,如前端Spriting雪碧圖,JS/CSS壓縮成一個文件等
- Inlining內聯的方式,採用inline css/inline js等併入html中,減少對css/js文件的請求
- CDN資源多域名轉發,靜態資源分佈存儲在多個域下。
以上三種三種方法雖然能使HTTP1.X協議傳輸速度提高,但也有對應的不足。
- 如雪碧圖,將多個小圖合併成一張大圖,降低多張小圖請求的高延遲,但是如果我只想要兩個icon小圖,卻需要加載一整張大圖,就會造成資源冗餘。合併的JS/CSS文件也有類似的問題。
- 內聯的方式,會讓我們的代碼變得難以維護,讓html文件變得更大,代碼混合嚴重。
- 多域名下可緩解Max-Connection,但不同域會讓Cookie信息無法彼此共享。
瞭解完HTTP1.1的痛點,接下來就是我們新一代的HTTP協議HTTP2.0
「 HTTP2.0」
前身SPDY
SPDY是2012年穀歌推出的是基於SSL/TLS的傳輸協議,SPDY有降低延遲,多路複用,頭部壓縮,服務端推送等特點,這些特點也稱為了後續HTTP2.0的功能基石,HTTP2.0是SPDY/3 draft的優化版。
HTTP2.0 與 SPDY的區別:
- HTTP2.0 頭部壓縮採用HPACK, 而SPDY採用DELEFT。
- HTTP2.0 理論上支持明文HTTP傳輸,而SPDY強制使用HTTPS。
多路複用
(一個域只要一個TCP連接)實現真正的併發請求,降低延時,提高了帶寬的利用率。
頭部壓縮
客戶端/服務端進行漸進更新維護,採用HPACK壓縮,節省了報文頭佔用流量。
- 相同的頭部信息不會通過請求發送,延用之前請求攜帶的頭部信息。
- 新增/修改的頭部信息會被加入到HEAD中,兩端漸進更新。
兩端會共同維護一個head list,每次請求時都會進行檢查。
該list包括:
- static (既定的頭部信息)
- dynamic (自定義的頭部信息)
請求優先級
每個流都有自己的優先級別,客戶端可指定優先級。並可以做流量控制。因為HTTP2.0的傳世允許請求併發,但是應用場景中我們要處理一些主要文件的優先級權重,以及資源模塊依賴等。所以我們可通過設置優先級來提高主要文件的權重,使其優先加載請求。
服務端推送
請求不是來自客戶端“明確”的請求,是從服務端PUSH_PROMISE幀中提供。例如我們加載index.html, 我們可能還需要index.js, index.css等文件。傳統的請求只有當拿到index.html,解析html中對index.js/index.css的引入才會再請求資源加載,但是通過服務端數據,可以提前將資源推送給客戶端,這樣客戶端要用到的時候直接調用即可,不用再發送請求。
- push的資源能緩存在瀏覽器中
- 不同的網頁能使用該緩存,不用重新發起
- push的資源通過multiplexed進行傳輸
- push的資源能夠進行priority標識
- client有權取消push資源的加載
- push的資源必須同域
二進制協議
HTTP2.0 傳輸協議採用二進制協議,區別與HTTP1.X的超文本協議。更易於幀,數據包的發送接收。HTTP2.0是運行在TCP連接上的應用層協議,接受服務器或發送請求時,會自動將頭部信息/request body分成HEAD幀和DATA幀。
客戶端/服務端發送/接收數據時,會將數據打散亂序發送,接收數據時接收一端再通過streamID標識來將數據合併。
HTTP2.0環境要求
HTTP2.0理論上支持明文HTTP傳輸,但因為其前身SPDY是在TLS上,他們的主人Google 和 Firefox 都支持TLS架構,所以需要搭建HTTP2.0 + TLS成了標準。
- Nginx > 1.10
- OpenSSL > 1.0.2
- CA證書
閱讀更多 程序猿的內心獨白 的文章