誇誇其談,簡單說說HTTP的優化歷程
theme: fancy
我正在參加「掘金·啟航計劃」
無論何時,只要去做網路請求相關的事情,都離不開
HTTP
(超文字傳輸)協議,它是Web
上任何資料交換的基礎,同時也是一個客戶端-伺服器協議;這些年間,HTTP經歷很多變化,也有助於塑造其靈活性,下面我們來簡單談談HTTP在各個版本做了哪些改變
通過本文,你將瞭解學習到如下內容
HTTP
這些年來,在迭代過程做了哪些優化,以及存在哪些不足?HTTP0.9
、Http1.0
和Http1.1
、SPDY
及2.0
、QUIC(HTTP 3.0)
各個版本的變化
HTTP/0.9—單行協議
在早期最初的HTTP
版本中,它非常簡單,也被稱為單行協議。顧名思義,請求由一行組成,並以唯一可能的方法開始,GET
後跟上資源的路徑,最終的響應也只包含檔案本身,沒有狀態碼和錯誤碼,並且由於沒有HTTP
標頭,它不能傳輸除HTML
以外的檔案
<html>
Hello World
</html>
HTTP/1.0—構建可擴充套件化
對於HTTP1.0,它最早在網頁中使用是1996年,而該版本的出現意味著在瀏覽器和伺服器中變得更加通用起來,引入了HTTP標頭的概念,讓協議變得非常靈活和可擴充套件。
感興趣的小夥伴可以檢視官方1996 年 11 月釋出了一份描述常見做法的資訊文件
它被稱為RFC 1945並定義了 HTTP/1.0
HTTP1.0
是一種無狀態、無連線的應用層協議。
- 它規定每次讓客戶端和伺服器都保持短連線,這也意味這它的連線是不復用的,每次在發起網路請求的時候都需要重寫建立TCP連線;
- 同時如果有多個網路請求的時候,它規定必須等待前一個請求響應之後,才會傳送下一個網路請求,這就是所謂的隊頭阻塞(head of line blocking)
HTTP/1.1—標準化協議
由於HTTP1.0
的網路使用效率非常低效,每次請求都需要重新建立TCP
連線,為了克服了諸多HTTP1.0
效能上的問題,HTTP1.1
出現了,作為HTTP
的第一個標準化版本HTTP/1.1
於 1997 年初發布,僅比 HTTP/1.0
晚了幾個月,並且在1999年廣泛運用於現在各大瀏覽器網路請求中
感興趣的小夥伴可以閱讀1997 年 1 月釋出的HTTP1.1的資訊文件RFC 2068
- 它可以重複使用連線,節省了響應的時間,引入了持久連線,不再需要多次開啟才能顯示嵌入在單個原始文件中的資源,預設開啟
Connection: keep-alive
- 引入了額外更多快取策略控制,例如
cache-control
等, 不單單隻有1.0中提供的headers
的expires
作為快取判斷標準 - 已經具備支援斷點續傳的能力,由於
HTTP/1.0
存在浪費頻寬的現象,客戶端只需要一部分資料,而服務端卻將全部資料傳送過來了;對此Http1.1
做了相應的頻寬優化,可以進行分塊響應,在header
引入了range
域,允許只請求一部分,讓開發者可充分利用頻寬,避免浪費 - 引入了內容協商,包括語言、編碼和型別。客戶端和伺服器現在可以就交換哪些內容達成一致,並且在錯誤通知管理上做了優化,增加了24個錯誤狀態碼,比如410表示服務端上資料被永久刪除等等
- 對於
Host
頭做了處理,一臺伺服器上可以有多個虛擬主機,共享同一個IP地址,這也意味著HTTP1.1
有從同一IP
地址託管不同域的能力
存在的缺陷
- 雖然
HTTP1.1
讓TCP
連線可以複用,但依舊沒有解決隊頭阻塞的問題,也就是後面的請求依然需要等待前一個請求完成後才能進行,不允許存在兩個並行的響應;由於所有請求都集中在一條連線中,在網路擁塞的情況下就很容易造成隊頭阻塞 - 相對低效的
TCP
利用,HTTP1.1
無法充分利用TCP
提供的所有效能,如果有多個請求的時候,HTTP1.0
會開啟多個TCP
連線來同時處理多個請求,這樣以來,當網路資源增多的時候,這個載入時間也會隨之增加。 - 由於隊首阻塞的問題,即便網路頻寬再打也無法被充分利用,對於網路延遲也是非常敏感的,過高的延遲會導致頁面訪問速度直線下滑
Google SPDY
SPDY
作為Google
開發的基於TCP
的應用層協議,目的就是為了提供網頁訪問速度和提高安全性;它對於之前的HTTP1.1
在效能上做了優化,它並不是一種HTTP
協議的替代方案,而是對HTTP
協議的增強,SPDY
主要有如下幾個方面的優勢:
SPDY
是允許在單個TCP
連線上多次請求,不需要單獨開放連線,有效避免了開啟多個TCP
連線造成的網路延遲,簡單來說,就是多路複用TCP
通道,降低HTTP
的高延時。- 對於多路複用,
SPDY
允許請求設定優先順序,不必像之前HTTP
一樣遵從先入先出的按順序處理請求。 - 頭部壓縮,捨棄掉了不必要的頭部資訊,可以節省一些等待時間。
- 基於SSL的安全傳輸,它是被
Google
強制使用的,經過SSL加密後,讓請求傳輸變得安全。
雖然SPDY
相對之前HTTP
版本來說已經很優秀了,但它依舊是使用文字格式解析的協議
HTTP/2.0—更高效能的協議
對於2010年Google
推出的SPDY
實驗性協議,它響應能力的提高並解決了重複資料傳輸的問題,作為了HTTP2.0
協議的基礎。對於HTTP2.0
的新特性,如下文所述:
-
HTTP2.0
相比之前版本的HTTP
和SPDY
最大的不同在於它的協議解析採用二進位制格式,目的是為了避免文字解析的天然缺陷,文字格式表現形式有很多不同,要考慮的場景很多,而由於二進位制格式只有0和1,所以會更加方便;HTTP2.0
為此專門增加了二進位制分幀層,將傳輸資訊分割成幀,並進行二進位制編碼- 幀的使用會更加便捷,更容易獲取到協議本身的內容
- 資料流以訊息的形式傳送,每個訊息是由一個或多個幀組成
-
由於是基於
SPDY
的改進的協議,它同樣是多路複用TCP
的,即所有請求通訊都在一個TCP
連線上完成;同時,服務端與客戶端是雙向實時通訊的,即連線共享; -
減少了網路返回傳輸的資料量,並且提高了相應網路的訪問速度,相比
HTTP1.x
請求資源的時間消耗更少 -
HTTP2.0
相比SPDY
同樣由加密組的限制,但不同的是,它允許明文傳輸,而SPDY
是強制進行SSL/TLS加密傳輸 -
壓縮請求頭,消除了傳輸資料的重複和開銷
-
伺服器推送,它允許伺服器通過稱為伺服器推送的機制在客戶端快取中填充資料
存在的缺陷
- 雖然
HTTP2.0
通過多路複用解決了HTTP
層,但本身是基於TCP
來實現的,所以在TCP
層依舊存在隊頭阻塞的問題,簡單來說,TCP
在收到資料包後,裡面的資料有可能是亂序的,TCP
需要排序整理之後才給上層使用,如果某個包丟失了,就必須要等待重傳,因為這個丟失的包從而導致了整個連線被阻塞了。 - 由於是基於
TCP
連線,總所周知,它是可靠的,面向連線的傳輸協議,但是它載入速度相對緩慢,而網路環境改變速度很快,歸根結底,其本質就是TCP
的問題。
QUIC(HTTP/3.0)
Google
2013年實現,QUIC
的出現旨在為 HTTP
連線提供更低的延遲,和HTTP2.0
一樣,它也是一個多路複用協議,到了2018年 這個基於QUIC
協議的HTTP
才正式被確認為HTTP3.0
;
感興趣的小夥伴可以閱讀官方HTTP3的資訊文件RFC 9114
QUIC
可以簡單理解為 HTTP 2.0 + TLS 1.3 + UDP的組合體,它的主要優勢如下所述:
- 解決了在連線複用中
HTTP 2.0 + TCP
存在的隊首阻塞問題,前面說過HTTP2.0
是執行在單個TCP
連線上的,因此TCP
層處理的丟包檢測和重傳可以阻止所有流,這樣的話是有可能導致隊首阻塞的,而QUIC
在UDP
上執行多個流,併為每個流獨立實現丟包檢測和重傳,這樣如果發生錯誤,只會阻塞該資料包中包含資料的流。 - 由於是基於
UDP
,所以可以靈活控制擁塞協議,並且它可以支援快速握手,減少了TCP
三次握手及TLS
握手的時間,並優化了失敗重傳策略和流量控制演算法。 - 連線遷移:採用了類似
Connection id
的特性,不需要在切換網路的時候重新連線,這樣使用者在使用APP
的體驗會更加流暢
- 請收下這些Kotlin開發必知必會的編碼實踐方式
- 日常思考,目前Kotlin協程能完全取代Rxjava嗎
- 誇誇其談,簡單說說HTTP的優化歷程
- 【一起學習開源框架】Retrofit相對於OKHttp,解決了什麼問題
- Kotlin Sequences Api:入門
- 【日常小問題】談談Rxjava中的操作符以及幾種常見的Subject,應用到實際場景中
- 【一起學習Android開源框架】Retrofit原始碼解析-1(第四部分)
- 【日常小問題】解決BottomSheetDialogFragment中多個fragment滑動衝突
- 【一起學習Android開源框架】Retrofit註解解析(第三部分)
- 【一起學習Android開源框架】Retrofit使用的代理模式解析(第二部分)
- 【一起學習Android開源框架】Retrofit的簡單使用(第一部分)