天天看點

HTTP協定之:HTTP/1.1和HTTP/2

簡介

HTTP/1.1

HTTP/2

傳輸模式對比

流優先級

緩沖區溢出處理

預測資源請求

壓縮

總結

HTTP的全稱是Hypertext Transfer Protocol,是在1989年World Wide Web發展起來之後出現的标準協定,用來在WWW上傳輸資料。HTTP/1.1是1997年在原始的HTTP協定基礎上進行的補充和優化。

到了2015年,為了适應快速發送的web應用和現代浏覽器的需求,發展出了新的HTTP/2協定,主要在手機浏覽器、延時處理、圖像處理和視訊處理方面進行了優化。

基本上所有的現代浏覽器都支援HTTP/2協定了,但是還有很多應用程式使用的是老的HTTP/1.1協定,本文将會介紹HTTP/1.1和HTTP/2的不同之處。

HTTP 1.0 是由Timothy Berners-Lee在1989年作為World Wide Web的标準協定釋出的。通常使用HTTP方法如:GET或者POST,以TEXT文本的形式在用戶端和伺服器端進行消息傳輸。

我們可以使用post man很友善的進行HTTP請求,如下所示:

用戶端通過GET請求,請求伺服器端的/index.html頁面,使用的協定是HTTP/1.1,伺服器端收到該請求之後,會将相應以文本的形式傳回給用戶端。

HTTP協定是對底層的TCP/IP協定的封裝,因為我們不需要交接具體的封包拆分和封裝的底層細節,隻需要關注于具體的業務邏輯即可,非常的友善。

HTTP/2是從SPDY協定發展出來的,它的發起者是Google,最初是為了在web互動中引入壓縮、多路複用等新的技術,最終在2015年被作為HTTP/2協定的一部分。

之前我們講到HTTP/1.1是以文本的形式進行傳輸的,這樣的缺點就是資料占用的空間比較大,相較于HTTP/1.1來說HTTP/2使用的是二進制進行傳輸的,使用二進制對消息進行封裝,同時保留了HTTP的語義,比如方法,頭等。

這種二進制的封裝對應用層是無感覺的,對于應用來說,還是按照常用的方法來建立HTTP請求,将其封裝成二進制的工作是由HTTP/2來完成的。

在HTTP1.0中,每當用戶端向伺服器端請求頁面的時候,往往傳回的不是一個完整的頁面,而是這個頁面還需要的額外的資源連結資訊,因為完整的頁面需要所有的資源都下載下傳完畢之後才能展示,是以在HTTP1.0中,用戶端需要中斷目前的連接配接,然後重建立立新的連接配接去請求資源。這會額外耗費多餘的資源和時間。

在HTTP1.1中,引入了持久連接配接和管道的概念,這樣不用每次請求都去重新開啟和建立連接配接,HTTP預設底層的TCP連接配接是open的,除非手動告訴它要去關閉。在這種情況下,用戶端可以使用同一個連接配接去和server進行互動,進而極大的提升HTTP的效率。

雖然在HTTP1.1中可以使用同一個連接配接進行資料傳輸了,但是對于這個連接配接來說,其中的請求是一一響應的,他們是有順序的。如果最前面的請求被阻塞了,後面的請求也得不到響應。這種情況被稱為head-of-line (HOL) blocking。

為了解決這個問題,可以在client和server端建立多個連接配接,這樣就可以利用多個connection并行進行資料的傳輸,進而提升傳輸效率。

但是這樣的缺點就是建立連接配接會消耗太多的資源,并且用戶端和伺服器端的連接配接個數也是有限的。

是以HTTP/2出現了。

在 HTTP/2 中,資料以二進制的的格式進行傳輸,其本身是将原始請求的切分成為更小的資訊包,進而大大增加了資料傳輸的靈活性。

HTTP1.1需要建立多個TCP連接配接進而解決并行傳輸的問題,但是在HTTP/2 中隻需要建立一個連接配接就夠了。在這個連接配接中可以傳輸多個資料流,每個資料流中又包含多個message包,每個message又被切分為多個資料frame。

這些資料frame可以在傳輸期間交換位置,然後在接收的另一端重新組裝。 交錯的請求和響應可以并行運作,進而不會阻塞它們背後的消息,這個過程被稱為多路複用。 多路複用的機制使得一個消息不用等待另外一個消息發送完成,進而解決了HTTP/1.1 中的隊頭阻塞問題。 這也意味着伺服器和用戶端可以發送并發請求和響應,進而實作更好的控制和更有效的連接配接管理。

多路複用雖然建構了多個消息流,但是隻占用了一個TCP連接配接,進而減少整個網絡的記憶體和處理占用空間,得到更好的網絡和帶寬使用率,進而降低整體營運成本。

單個TCP連接配接還提高了HTTPS協定的性能,因為用戶端和伺服器可以為多個請求/響應重用相同的安全會話。 在HTTPS中,在TLS或SSL握手期間,雙方在整個會話期間使用單個密鑰。 如果連接配接中斷從新開始新的會話,則需要新生成的密鑰進行進一步通信。 是以,維護單個連接配接可以大大減少HTTPS所需的資源。

請注意,盡管HTTP/2規範并未強制要求使用TLS,但許多主要浏覽器僅支援帶有HTTPS的HTTP/2。

雖然HTTP/2解決了多個資料frame通常傳輸的問題,但是對于同一個資源來說,必須要等到的所有的資料frame都接受完畢之後才能展示,如果我們想優先展示某個資源該怎麼做呢?

HTTP/2提供了流優先級的解決方案。

在用戶端向伺服器端發送消息的時候,消息會以流的形式在連接配接中傳輸,這些流可以配置設定1到256之間的權重來确定其請求的響應的優先級。 數字越大表示優先級越高。 除此之外,用戶端還通過指定它所依賴的流的ID來說明每個流對另一個流的依賴關系。 如果省略父辨別符,則認為該流依賴于根流。

伺服器會使用流中的ID建構一個依賴樹,進而确定其相應的順序。

應用程式的開發人員可以根據需要自行設定請求的優先級,比如在網頁中提供低分辨率的縮略圖的同時提供低優先級的高分辨率的圖像。通過為資源配置設定不同的優先級,開發人員能夠更好地控制網頁渲染。

不管是哪種協定,用戶端和伺服器端在接收資料的時候都有一個緩沖區來臨時存儲暫時處理不了的資料,但是緩沖區的大小是有限制的,是以有可能會出現緩沖區溢出的情況,比如用戶端向伺服器端上傳一個大的圖檔,就有可能導緻伺服器端的緩沖區溢出,進而導緻一些額外的資料包丢失。

為了避免緩沖區溢出,各個HTTP協定都提供了一定的解決辦法。

在HTTP1.1中,流量的控制依賴的是底層TCP協定,在用戶端和伺服器端建立連接配接的時候,會使用系統預設的設定來建立緩沖區。在資料進行通信的時候,會告訴對方它的接收視窗的大小,這個接收視窗就是緩沖區中剩餘的可用空間。如果接收視窗大小為零,則說明接收方緩沖區已滿,則發送方将不再發送資料,直到用戶端清除其内部緩沖區,然後請求恢複資料傳輸。

因為HTTP1.1使用多個TCP連接配接,多以可以對每一個TCP連接配接進行單獨的流量控制。但是HTTP2使用的是多路複用的模式,是以它的流量控制方式和HTTP1.1是不同的。

HTTP2是通過用戶端和伺服器端的應用中進行緩沖區大小消息的傳輸,是通過在應用層層面控制資料流,是以各個應用端可以自行控制流量的大小,進而實作更高的連接配接效率。

HTTP/2提供了更詳細的控制級别,進而開啟了更大優化的可能性。

在一個典型的web應用中,當用戶端發動一個GET請求到伺服器端的時候,通常用戶端會發現是以需要的不止一個資源,還可能包含了CSS或者其他JS等資源。但是用戶端隻有在首次擷取到伺服器端的響應時候才能真正确認到底需要哪些資源。然後需要額外請求這些資源以完成整個請求。但是這些額外的請求最終會增加連接配接加載時間。

那麼有沒有可能伺服器在用戶端請求之前将資源發送給用戶端呢?我們看下HTTP1.1和HTTP2是怎麼做的。

在HTTP1.1中,主要使用的資源内聯的方式,比如将用戶端所需要的CSS或者JS資源包含在伺服器最初發送的HTML文檔中,也就是做内聯操作,進而減少用戶端必須發送的請求總數。

但是這樣的解決方案也有問題。因為一般來說資源内聯一般是針對較小的資源來說的,如果資源檔案太大的話,就會大大的增加HTML檔案的大小,進而抵消減少連接配接提升的速度優勢。

另外如果資源被放在HTML中,那麼用戶端就沒有可能對這些資源進行緩存,進而影響整體的效率。

在HTTP/2中使用的是伺服器推送。因為HTTP/2在同一個連接配接中可以發送多個stream,是以伺服器可以将資源與請求的HTML頁面一起發送到用戶端,在用戶端請求之前提供資源。 這個過程被稱為伺服器推送。

這樣就可以在不用新開連接配接的同時,實作HTML文檔和資源的分離和同時推送。

但是在HTTP/2中,伺服器推送是由應用程式來控制的,是以控制起來會比較複雜。我們會在後續的文章中詳細講解HTTP/2的伺服器推送。

通常為了減少資料在網絡中的傳輸,我們需要對資料進行壓縮,接下來我們看一下在HTTP1.1和HTTP2中都是怎麼做的。

在HTTP1.1中,通常使用gzip對HTTP中的消息進行壓縮,主要是針對CSS檔案和javascript檔案,但是HTTP的消息頭還是由純文字來發送的,另外由于cookie的使用,導緻HTTP消息頭的大小會越來越大,進而對程式的性能造成一定的影響。

在HTTP/2中,使用的算法是HPACK算法,同時可以對HTTP頭和資料分别進行壓縮,進而大大減少其大小。

HTTP/2在HTTP1.1的基礎上進行了更加細粒度的優化控制,并提供了包括多路複用、流優先級、流量控制、伺服器推送和壓縮等進階特性。非常強大。希望大家能夠喜歡。

最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!