大家好,我是Tom哥~
今天跟大家聊聊下 HTTP協議,歡迎留言討論
互聯網時代,足不出戶,點點鼠標就可以輕松了解外面的世界變化,這一切得益于網絡傳輸數據。
我們都知道網絡有7層模型,從底層到上層依次是:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。
越往上,越接近用戶習慣,更容易被用戶直觀了解。
今天講的 HTTP 協議屬于應用層協議,也是互聯網廣泛使用的基礎協議之一。
一、 HTTP/0.9
0.9 版本是HTTP最早的版本,誕生于 1991 年,比較簡單。
1、只支持 GET 請求,沒有請求頭。每次請求都要單獨創建一個TCP連接,復用性差,性能不高
2、服務端響應的數據只能是 HTML格式,服務器發送完畢,會關閉TCP連接。如果請求的頁面不存在,也不會返回任何錯誤碼。
當時,互聯網剛起步,頁面展現形式更多是文本為主,能滿足基本需求。隨著用戶需求的多樣化,對展示形態和性能也提出了更高要求,HTTP協議也開始了慢慢的升級之路。
二、 HTTP/1.0
1996年,HTTP/1.0 發布,相比之前版本增加了很多特性。
1、請求和響應增加了頭信息(header),用來描述一些元數據,如:
- Content-Type 讓響應數據不只限于超文本
- Expires、Last-Modified 緩存
- Authorization 身份認證
- Connection: keep-alive 支持長連接,但非標準
2、請求方法,除了 GET,還增加了 POST、HEAD命令,豐富了互動方式
3、豐富了傳輸內容的格式,有文本、圖像、視頻、二進制文件
4、請求時增加 HTTP 協議版本,響應端增加狀態碼。
缺點:
主要還是連接復用問題,每個TCP連接只能發送一個請求。當數據發送完畢后,連接就會關閉。由于TCP建立連接,需要三次握手,所以性能會比較差。
為了緩解這個問題,請求頭引入一個非標準的Connection字段:Connection: keep-alive,要求服務器不要關閉TCP連接,從而達到復用效果。
當然,這個不是標準字段,只是一個臨時方案。
三、 HTTP/1.1
1997年,HTTP/1.1 版本發布。進一步完善了HTTP協議,也是目前最流行的版本,一直活躍至今。
1、默認支持長連接(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲
2、管線化技術。支持多個 HTTP 請求批量發送,不用排隊,這就解決了 HTTP 隊頭阻塞問題。但批量發送的 HTTP 請求,必須按照發送的順序返回響應
3、流式渲染,響應端可以不用一次返回所有數據,可以將數據拆分成多個模塊,產生一塊數據,就發送一塊數據,這樣客戶端就可以同步對數據進行處理,減少響應延遲,降低白屏時間。
4、請求頭引入了range頭域,它允許只請求資源的某個部分,即返回碼是206(Partial Content),這樣就方便了開發者自由的選擇以便于充分利用帶寬和連接
5、增加 Host 頭,實現了虛擬主機技術,將一臺服務器分成若干個主機,這樣就可以在一臺服務器上部署多個網站了。通過配置 Host 的域名和端口號,即可支持多個 HTTP 服務
6、頭部增加一些緩存字段,如 E-Tag、Cache-Control 等
7、新增了24個錯誤狀態響應碼,如 409(Conflict)表示請求的資源與資源的當前狀態發生沖突;410(Gone)表示服務器上的某個資源被永久性的刪除。
小結:
請求和響應成對出現,順序串行。如果按QPS來理解的話,最大的并發數只能是 1
四、 HTTP/2
HTTP/2 誕生于 2015 年,最大特點是基于二進制的特性,對 HTTP 傳輸效率進行了深度優化。
新增了哪些特性?
1、二進制幀
HTTP/2 將一個 HTTP 請求劃分為 3 個部分:二進制幀、消息、數據流
- 幀:一段二進制數據,是 HTTP/2 傳輸的最小單位
- 消息:邏輯上的 HTTP 消息,比如請求、響應等,由一或多個幀組成
- 數據流:連接中的一個虛擬信道,可以同時承載一條或多條消息,支持雙向承載
一個TCP連接上,承載著雙向消息,一條消息包含多個二進制幀,每個幀都有唯一標識,來自不同數據流的幀可以交錯發送,然后再根據每個幀頭的數據流標識符重新組裝,這樣就實現了數據傳輸。
2、多路復用
HTTP/1.1 中的 KeepAlive 長連接雖然可以傳輸很多請求,但它的吞吐量很低,因為在發出請求等待響應的那段時間里,這個長連接不能做任何事!而 HTTP/2 通過 Stream 這一設計,允許請求并發傳輸。因此,HTTP/1.1 時代 Chrome 通過 6 個連接訪問頁面的速度,遠遠比不上 HTTP/2 單連接的速度。
HTTP/2 的并發性能比 HTTP/1.1 通過 TCP 連接實現并發要高。這是因為,當 HTTP/2 實現 100 個并發 Stream 時,只經歷 1 次 TCP 握手、1 次 TCP 慢啟動以及 1 次 TLS 握手,但 100 個 TCP 連接會把上述 3 個過程都放大 100 倍!
3、頭部壓縮
HTTP/1.1 的頭部字段包含大量信息,而且每次請求都得帶上,占用了大量的帶寬。
HTTP/2 靜態表僅用一個數字來表示,其中,映射數字與字符串對應關系的表格,被寫死在 HTTP/2 實現框架中。這樣的編碼效率非常高,
什么是靜態表呢?HTTP/2 將 61 個高頻出現的頭部,比如描述瀏覽器的 User-Agent、GET 或 POST 方法、返回的 200 SUCCESS 響應等,分別對應 1 個數字再構造出 ”字典“,并寫入 HTTP/2 客戶端與服務端,用索引號表示重復的字符串,可以達到 50%~90% 的高壓縮率。
4、請求優先級
由于采用多路復用,多個請求會同時產生多個數據流,數據流中有一個優先級的標識,服務端根據這個標識決定響應的優先順序。
流 ID 不能重用,只能順序遞增,客戶端發起的 ID 是奇數,服務器端發起的 ID 是偶數;
5、服務器端推送
HTTP/1.1 不支持服務器主動推送消息,因此當客戶端需要獲取通知時,只能通過定時器不斷地輪詢拉取消息。HTTP/2 的消息推送結束了無效率的定時拉取,節約了大量帶寬和服務器資源。
例如:HTTP/1.1 中請求一個頁面時,瀏覽器會先發送一個 HTTP 請求,然后得到響應的 HTML 內容并開始解析,如果發現有<script src="xxxx.js">標簽,則會再次發起 HTTP 請求獲取對應的 JS 內容。而 HTTP/2 可以在返回 HTML 的同時,將需要用到的 JS、CSS 等內容一并返回給客戶端,當瀏覽器解析到對應標簽時,也就不需要再次發起請求了。
小結:
通過二進制幀流模式,打破之前的”請求 - 應答“串行模式,單個TCP連接上支持并發請求、響應,多路復用大大提升了網絡吞吐量。
HTTP/2 作為升級版,為了與之前的版本保持兼容,對頭字段、狀態碼、請求方法等信息都保留不變,降低了學習成本,同時上層應用也可以做到無縫兼容。
小提示:
做軟件架構也是一樣,設計接口規范時一定要慎之又慎,盡量預留很長一段時間的擴展,后續更多是對里面的邏輯優化重構,對外黑盒,無需感知。
為什么是 HTTP/2 ,而不是HTTP/2.0 ?
HTTP/2 工作組特別給出了解釋,以前的1.0、1.1 容易讓人誤解,實際使用中難以區分,所以,決定后續的版本不在使用小版本,一律采用大版本。
所以,接下來,你只會看到 HTTP/2 、HTTP/3 ...
關于加密
為了滿足安全性,HTTP/2分別支持”加密“和”明文“,定義兩個字符串標識符:“h2”表示加密的 HTTP/2,“h2c”表示明文的 HTTP/2,多出的那個字母“c”的意思是“clear text”。
五、 HTTP/3
HTTP/2 雖然使用“幀”、“流”“多路復用”,沒有了“隊頭阻塞”,但這些優化技巧都是在應用層里,而在底層,也就是 TCP 協議里,還是會發生“隊頭阻塞”。
HTTP/2 把多個請求 - 響應分解成流,交給 TCP 后,TCP 會再拆成更小的段(segment)依次發送。如果網絡不好時,會發生丟包。
TCP為了保證可靠性傳輸,會有丟包重傳機制。這樣,其他的包即使已經收到了,也只能放在緩沖區里,這樣就又出現了隊頭阻塞,這是TCP協議固有的。
為了解決這個問題,Google推出了QUIC協議,讓 HTTP 跑在 QUIC 上而不是 TCP 上,這個新版本,我們稱之為 HTTP/3
HTTP/3 目前還處于草案階段,離正式發布還有段時間,我們拭目以待...
【編輯推薦】https://mp.weixin.qq.com/s/zn1aJMoNH9B741EoLBJcgA