簡介
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.1
HTTP 1.0 是由Timothy Berners-Lee在1989年作為World Wide Web的標準協議釋出的。通常使用HTTP方法如:GET或者POST,以TEXT文字的形式在客戶端和伺服器端進行訊息傳輸。
我們可以使用post man很方便的進行HTTP請求,如下所示:
GET /index.html HTTP/1.1
Host: www.flydean.com
客戶端通過GET請求,請求伺服器端的/index.html頁面,使用的協議是HTTP/1.1,伺服器端收到該請求之後,會將相應以文字的形式返回給客戶端。
HTTP協議是對底層的TCP/IP協議的封裝,因為我們不需要交接具體的報文拆分和封裝的底層細節,只需要關注於具體的業務邏輯即可,非常的方便。
HTTP/2
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的基礎上進行了更加細粒度的優化控制,並提供了包括多路複用、流優先順序、流量控制、伺服器推送和壓縮等高階特性。非常強大。希望大家能夠喜歡。
本文已收錄於 http://www.flydean.com/02-http1-1-vs-http2/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!