介紹 超文本傳輸協議(HTTP)是一種應用協議,自1989年發明以來,它一直是事實上在萬維網上進行通信的標准。從1997年發布HTTP/1.1到最近,對它的修改很少。協議。但是在2015年,重新構想的版本稱為HTTP/2投入使用,它提供了幾種減少延遲的方法,尤其是在處理移動平台以及服務器密集型圖形和視頻時。此后HTTP/2變得越來越流行,據估計,世界上約有三分之一的網站都支持HTTP/2。在這種瞬息萬變的格局中,Web開發人員可以從了解HTTP/1.1和HTTP/2之間的技術差異中受益,從而使他們可以就不斷發展的最佳實踐做出明智而有效的決策。
閱讀本文之后,您將了解HTTP/1.1和HTTP/2之間的主要區別,重點介紹HTTP/2為實現更有效的Web協議而采取的技術更改。
背景
為了具體說明HTTP/2對HTTP/1.1所做的特定更改,讓我們首先從較高的角度看一下它們的歷史發展和基本工作。
HTTP/1.1
HTTP由Timothy Berners-Lee於1989年開發,作為萬維網的通信標准,HTTP是一種頂級應用程序協議,它在客戶端計算機與本地或遠程Web服務器之間交換信息。在此過程中,客戶端通過調用類似或的方法向服務器發送基於文本的請求。作為響應,服務器將HTML頁面之類的資源發送回客戶端。GETPOST
例如,假設您正在訪問域中的網站www.example.com。當您導航到該URL時,計算機上的Web瀏覽器會以基於文本的消息的形式發送HTTP請求,類似於以下所示:
GET /index.html HTTP/1.1 Host: www.example.com
該請求使用的GET方法,該方法從后面列出的主機服務器中請求數據Host:。響應此請求,example.comWeb服務器將HTML頁面返回到發出請求的客戶端,此外還包含HTML中要求的任何圖像,樣式表或其他資源。請注意,在第一次數據調用中,並非所有資源都會返回給客戶端。請求和響應將在服務器和客戶端之間來回移動,直到Web瀏覽器收到在屏幕上呈現HTML頁面內容所需的所有資源為止。
您可以將這種請求和響應的交換視為Internet協議棧的單個應用程序層,它位於傳輸層(通常使用傳輸控制協議或TCP)和網絡層(使用Internet協議或IP )之上):
關於此堆棧的較低層,有很多要討論的內容,但是為了獲得對HTTP/2的高層了解,您只需要知道此抽象層模型以及HTTP進入其中的位置即可。
借助HTTP/1.1的基本概述,我們現在可以繼續講述HTTP/2的早期開發。
HTTP/2
HTTP/2最初是SPDY協議,最初由Google開發,旨在通過使用壓縮,復用和優先級等技術來減少網頁加載延遲。當IETF(互聯網工程任務組)的超文本傳輸協議工作組httpbis 將該標准放在一起時,此協議充當HTTP/2的模板,並最終在2015年5月發布了HTTP/2。從一開始,許多瀏覽器支持這項標准化工作,包括Chrome,Opera,Internet Explorer和Safari。自2015年以來,部分原因是由於該瀏覽器的支持,該協議的采用率非常高,新站點中的采用率尤其高。
從技術角度來看,區別HTTP/1.1和HTTP/2的最重要功能之一是二進制框架層,可以將其視為Internet協議棧中應用程序層的一部分。與HTTP/1.1(以純文本格式保留所有請求和響應)相反,HTTP/2使用二進制框架層以二進制格式封裝所有消息,同時仍保持HTTP語義,例如動詞,方法和標頭。應用程序級API仍將以傳統的HTTP格式創建消息,但是基礎層隨后會將這些消息轉換為二進制。這樣可以確保在與新協議進行交互時,在HTTP/2之前創建的Web應用程序可以繼續正常運行。
將消息轉換為二進制,HTTP/2可以嘗試HTTP/1.1中沒有的新的數據傳輸方法,這是兩種協議之間實際差異的根本原因。下一節將介紹HTTP/1.1的交付模型,然后介紹HTTP/2帶來了哪些新模型。
投放模式
如上一節所述,HTTP/1.1和HTTP/2共享語義,使用熟悉的方法(如GET和),確保在兩種協議之間在服務器和客戶端之間傳輸的請求和響應作為具有標題和正文的傳統格式的消息到達目的地POST。但是,盡管HTTP/1.1以純文本消息形式傳輸這些消息,但HTTP/2卻將它們編碼為二進制,從而提供了截然不同的傳遞模型可能性。在本節中,我們將首先簡要研究HTTP/1.1如何通過其交付模型來嘗試優化效率以及由此產生的問題,然后是HTTP/2二進制框架層的優勢以及如何確定優先級的描述。要求。
HTTP/1.1 —流水線和行頭阻塞
客戶端在HTTP GET請求上收到的第一個響應通常不是完全呈現的頁面。相反,它包含指向所請求頁面所需的其他資源的鏈接。客戶端發現只有在下載頁面后,頁面的完整呈現才需要服務器提供這些額外資源。因此,客戶端將不得不提出其他請求來檢索這些資源。在HTTP/1.0中,客戶端必須中斷並重新建立與每個新請求的TCP連接,這在時間和資源上都是一項昂貴的事務。
HTTP/1.1通過引入持久連接和流水線處理了這個問題。對於持久連接,HTTP/1.1假定TCP連接應該保持打開狀態,除非直接告知要關閉。這允許客戶端通過同一連接發送多個請求,而不必等待每個請求的響應,從而大大提高了HTTP/1.1相對於HTTP/1.0的性能。
不幸的是,這種優化策略存在一個自然的瓶頸。由於多個數據包在到達同一目的地時無法相互傳遞,因此在某些情況下,隊列開頭的無法檢索其所需資源的請求將阻止其后的所有請求。這被稱為行頭(HOL)阻止,並且在優化HTTP/1.1中的連接效率方面是一個重大問題。添加單獨的並行TCP連接可以緩解此問題,但是客戶端和服務器之間可能存在的並發TCP連接的數量受到限制,並且每個新連接都需要大量資源。
這些問題在HTTP/2開發人員的思想中居首位,他們提議使用上述二進制框架層來解決這些問題,您將在下一節中詳細了解該主題。
HTTP/2 —二進制框架層的優點
在HTTP/2中,二進制幀層對請求/響應進行編碼,並將其切成較小的信息包,從而大大提高了數據傳輸的靈活性。
讓我們仔細看看它是如何工作的。與HTTP/1.1(必須使用多個TCP連接來減輕HOL阻塞的影響)相反,HTTP/2在兩台計算機之間建立了一個連接對象。在此連接內,有多個數據流。每個流由熟悉的請求/響應格式的多個消息組成。最后,每條消息都分成較小的單元,稱為框架:

從最細粒度的角度講,通信通道由一堆二進制編碼的幀組成,每個幀都標記到特定的流。識別標簽允許連接在傳輸過程中交織這些幀,並在另一端重新組裝它們。交錯的請求和響應可以並行運行,而不會阻塞后面的消息,這一過程稱為multiplexing。通過確保沒有消息等待其他消息完成,多路復用解決了HTTP/1.1中的行頭阻塞問題。這也意味着服務器和客戶端可以發送並發請求和響應,從而實現更好的控制和更有效的連接管理。
由於多路復用允許客戶端並行構造多個流,因此這些流僅需要利用單個TCP連接。每個起點只有一個持久連接,可以通過減少整個網絡的內存和處理占用空間來改善HTTP/1.1。這導致更好的網絡和帶寬利用率,從而降低了總體運營成本。
單個TCP連接還可以提高HTTPS協議的性能,因為客戶端和服務器可以將相同的安全會話重用於多個請求/響應。在HTTPS中,在TLS或SSL握手期間,雙方都同意在整個會話過程中使用單個密鑰。如果連接斷開,則新的會話開始,需要新生成的密鑰用於進一步的通信。因此,維護單個連接可以大大減少HTTPS性能所需的資源。請注意,盡管HTTP/2規范沒有強制要求使用TLS層,但許多主流瀏覽器僅支持HTTP/2和HTTPS。
盡管二進制框架層中固有的多路復用解決了HTTP/1.1的某些問題,但是等待相同資源的多個流仍然會導致性能問題。HTTP/2的設計考慮了這一點,但是,通過使用流優先級,我們將在下一節中討論這個主題。
HTTP/2 —流優先級
流優先級划分不僅解決了爭用同一資源的請求的可能問題,而且還允許開發人員自定義請求的相對權重,以更好地優化應用程序性能。在本節中,我們將分解優先級划分過程,以便更好地了解如何利用HTTP/2的此功能。
眾所周知,二進制框架層將消息組織成並行的數據流。當客戶端將並發請求發送到服務器時,它可以通過為每個流分配1到256之間的權重來區分請求的響應的優先級。數字越高表示優先級越高。除此之外,客戶端還通過指定流所依賴的流的ID來聲明每個流對另一流的依賴性。如果省略了父標識符,則認為該流依賴於根流。下圖對此進行了說明:

在圖示中,該頻道包含六個流,每個流具有唯一的ID並與特定的權重關聯。流1沒有與其關聯的父ID,並且默認情況下與根節點關聯。所有其他流都標記了一些父ID。每個流的資源分配將基於它們所擁有的權重及其所需的依賴關系。例如,在圖中已分配了相同權重和相同父流的流5和6,將具有相同的資源分配優先級。
服務器使用此信息來創建依賴關系樹,該依賴關系樹允許服務器確定請求檢索其數據的順序。根據上圖中的流,依賴關系樹如下:

在此依賴關系樹中,流1依賴於根流,並且沒有其他從根派生的流,因此所有可用資源將在其他流之前分配給流1。由於樹表明流2取決於流1的完成,因此直到流1任務完成,流2才繼續進行。現在,讓我們看一下流3和4。這兩個流都依賴於流2。與流1的情況一樣,流2將獲得流3和4之前的所有可用資源。流2完成其任務后,流3和4將獲得資源;如它們的權重所示,它們按2:4的比例進行分配,從而導致流4的資源更多。最后,當流3完成時,流5和6將獲得相等的可用資源。即使流4接收到更多的資源,這也可能在流4完成其任務之前發生。較高級別的從屬流結束后,就可以開始較低級別的流。
作為應用程序開發人員,您可以根據需要在請求中設置權重。例如,在網頁上提供縮略圖后,可以為較低的優先級分配高分辨率的圖像。通過提供這種權重分配功能,HTTP/2使開發人員可以更好地控制網頁渲染。該協議還允許客戶端響應於用戶交互而在運行時更改依賴關系並重新分配權重。但是,請務必注意,如果某個流被阻止訪問特定資源,則服務器可以自行更改分配的優先級。
緩沖區溢出
在兩台機器之間的任何TCP連接中,客戶端和服務器都有一定數量的緩沖區空間可用於容納尚未處理的傳入請求。除了下游和上游連接的速度不均勻之外,這些緩沖區還提供了靈活性,可以解決眾多或特別大的請求。
但是,在某些情況下,緩沖區不足。例如,由於緩沖區大小有限或帶寬較低,服務器可能以客戶端應用程序無法應對的速度推送大量數據。同樣,當客戶端將巨大的圖像或視頻上傳到服務器時,服務器緩沖區可能會溢出,從而導致一些其他數據包丟失。
為了避免緩沖區溢出,流控制機制必須防止發送方用數據淹沒接收方。本節將概述HTTP/1.1和HTTP/2如何根據其不同的傳遞模型使用此機制的不同版本來處理流控制。
HTTP/1.1
在HTTP/1.1中,流控制依賴於基礎TCP連接。啟動此連接時,客戶端和服務器均使用其系統默認設置來建立其緩沖區大小。如果接收方的緩沖區部分填充了數據,它將告訴發送方其接收窗口,即,緩沖區中剩余的可用空間量。該接收窗口在稱為ACK數據包的信號中公告,這是接收器發送的數據包,用於確認已接收到打開信號。如果此公告的接收窗口大小為零,則發送方將不再發送任何數據,直到客戶端清除其內部緩沖區,然后請求恢復數據傳輸為止。在此處需要注意的重要一點是,使用基於基礎TCP連接的接收窗口只能在連接的任一端實現流控制。
因為HTTP/1.1依賴傳輸層來避免緩沖區溢出,所以每個新的TCP連接都需要單獨的流控制機制。但是,HTTP/2在單個TCP連接中多路復用流,並且必須以不同的方式實現流控制。
HTTP/2
HTTP/2在單個TCP連接中多路復用數據流。結果,TCP連接級別的接收窗口不足以調節單個流的傳遞。HTTP/2通過允許客戶端和服務器實現自己的流控制,而不是依靠傳輸層來解決此問題。應用程序層傳達可用的緩沖區空間,從而允許客戶端和服務器在多路復用流的級別上設置接收窗口。在通過WINDOW_UPDATE框架進行初始連接后,可以修改或保持這種精細的流量控制。
由於此方法在應用程序層的級別上控制數據流,因此在調整接收窗口之前,流控制機制不必等待信號到達其最終目的地。中間節點可以使用流控制設置信息來確定自己的資源分配並相應地進行修改。這樣,每個中間服務器都可以實現自己的自定義資源策略,從而提高連接效率。
在創建適當的資源策略時,流控制的這種靈活性可能是有利的。例如,客戶端可以獲取圖像的第一次掃描,將其顯示給用戶,並允許用戶預覽圖像,同時獲取更多關鍵資源。客戶端獲取這些關鍵資源后,瀏覽器將恢復圖像剩余部分的檢索。因此,將流控制的實現推遲到客戶端和服務器可以提高Web應用程序的感知性能。
在前面一節中提到的流控制和流優先級方面,HTTP/2提供了更詳細的控制級別,為進一步優化提供了可能。下一節將說明該協議特有的另一種方法,該方法可以通過類似的方式增強連接:使用服務器push預測資源請求。
預測資源請求
在典型的Web應用程序中,客戶端將發送GET請求並接收HTML頁面,通常是網站的索引頁面。在檢查索引頁面內容時,客戶端可能發現它需要獲取其他資源(例如CSS和JavaScript文件)才能完全呈現頁面。客戶端僅在收到其初始GET請求的響應后,才確定需要這些額外的資源,因此客戶端必須提出其他請求以獲取這些資源並完成將頁面放在一起。這些額外的請求最終會增加連接加載時間。
但是,有一些解決方案可以解決此問題:由於服務器預先知道客戶端將需要其他文件,因此服務器可以通過在請求這些資源之前將這些資源發送給客戶端來節省客戶端時間。HTTP/1.1和HTTP/2具有實現此目的的不同策略,每種策略將在下一節中介紹。
HTTP/1.1 —資源內聯
在HTTP/1.1中,如果開發人員事先知道客戶端計算機需要呈現頁面的哪些其他資源,則他們可以使用一種稱為資源內聯的技術將所需資源直接包含在服務器為響應該請求而發送的HTML文檔中。最初的GET要求。例如,如果客戶端需要特定的CSS文件來呈現頁面,則內聯該CSS文件將在客戶端請求之前為客戶端提供所需的資源,從而減少了客戶端必須發送的請求總數。
但是資源內聯存在一些問題。對於較小的基於文本的資源,將資源包括在HTML文檔中是一個可行的解決方案,但是非文本格式的較大文件會大大增加HTML文檔的大小,最終會降低連接速度並抵消最初獲得的優勢使用這項技術。而且,由於內聯資源不再與HTML文檔分開,因此客戶端沒有機制可以拒絕客戶端已經擁有的資源或將資源放入其緩存中。如果有多個頁面需要該資源,則每個新HTML文檔的代碼中都將內聯相同的資源,這導致HTML文檔更大,並且加載時間比起初僅在資源中進行緩存的時間長。
因此,資源內聯的主要缺點是客戶端無法分離資源和文檔。需要更好的控制級別來優化連接,HTTP/2試圖通過服務器推送來滿足這一需求。
HTTP/2 —服務器推送
由於HTTP/2啟用了對客戶端初始GET請求的多個並發響應,因此服務器可以將資源與請求的HTML頁面一起發送到客戶端,從而在客戶端請求之前提供資源。此過程稱為服務器推送。這樣,HTTP/2連接可以實現資源內聯的相同目標,同時保持推送資源與文檔之間的分隔。這意味着客戶端可以決定與主HTML文檔分開緩存或拒絕推送的資源,從而解決了資源內聯的主要缺點。
在HTTP/2中,當服務器發送一個PUSH_PROMISE幀以通知客戶端它將推送資源時,此過程開始。該幀僅包含消息的標頭,並允許客戶端提前知道服務器將推送哪個資源。如果已經緩存了資源,則客戶端可以通過發送RST_STREAM幀作為響應來拒絕推送。該PUSH_PROMISE框架還可以避免客戶端向服務器發送重復請求,因為它知道服務器將要推送的資源。
在此必須注意,服務器推送的重點是客戶端控制。如果客戶端需要調整服務器推送的優先級,甚至禁用它,它可以隨時發送一個SETTINGS幀來修改此HTTP/2功能。
盡管此功能具有很大的潛力,但服務器推送並非始終是優化Web應用程序的答案。例如,即使客戶端已經緩存了資源,某些Web瀏覽器也無法始終取消推送的請求。如果客戶端錯誤地允許服務器發送重復資源,則服務器推送可能會不必要地耗盡連接。最后,服務器推送應由開發人員自行決定。有關如何從戰略上使用服務器推送和優化Web應用程序的更多信息,請查看Google開發的PRPL模式。要了解有關服務器推送的可能問題的更多信息,請參閱Jake Archibald的博客文章HTTP/2 push比我想象的要難。
壓縮
優化Web應用程序的常用方法是使用壓縮算法來減少在客戶端和服務器之間傳輸的HTTP消息的大小。HTTP/1.1和HTTP/2都使用此策略,但是前者中存在實現問題,無法壓縮整個消息。下一節將討論為什么會這樣,以及HTTP/2如何提供解決方案。
HTTP/1.1
長期以來,諸如gzip之類的程序一直被用於壓縮HTTP消息中發送的數據,尤其是減小CSS和JavaScript文件的大小。但是,消息的標題部分始終以純文本形式發送。盡管每個標頭都非常小,但是隨着提出更多請求,此未壓縮數據的負擔會越來越重,特別是對復雜,需要大量API且需要許多不同資源請求的Web應用程序造成不利影響。另外,cookie的使用有時會使標頭大得多,從而增加了對某種壓縮的需求。
為了解決此瓶頸,HTTP/2使用HPACK壓縮來縮小標頭的大小,這一主題將在下一節中進一步討論。
HTTP/2
HTTP/2中一次又一次出現的主題之一是它使用二進制框架層對更好的細節表現出更大控制的能力。在頭壓縮方面也是如此。HTTP/2可以從其數據中拆分標頭,從而生成標頭幀和數據幀。然后,特定於HTTP/2的壓縮程序HPACK可以壓縮此標頭幀。該算法可以使用霍夫曼編碼對標頭元數據進行編碼,從而大大減小其大小。此外,HPACK可以跟蹤先前傳送的元數據字段,並根據客戶端和服務器之間共享的動態更改的索引進一步壓縮它們。例如,接受以下兩個請求:

在這些請求的各種領域中,如method,scheme,host,accept,和user-agent,具有相同的值; 只有path字段使用不同的值。結果,在發送時Request #2,客戶端可以使用HPACK僅發送重建這些公共字段和對該path字段進行新編碼所需的索引值。結果頭幀將如下所示:
使用HPACK和其他壓縮方法,HTTP/2提供了另一項功能,可以減少客戶端-服務器延遲。
結論
從此逐點分析中可以看出,HTTP/2在許多方面與HTTP/1.1有所不同,其中一些功能提供了更高級別的控制,可用於更好地優化Web應用程序性能,而其他功能則可以在先前的協議。現在,您已經對這兩種協議之間的變化有了一個高級的了解,現在可以考慮HTTP/2中的多路復用,流優先級,流控制,服務器推送和壓縮等因素如何影響Web開發的不斷變化的格局。 。
如果您希望看到HTTP/1.1和HTTP/2之間的性能比較,請查看此Google演示,該演示比較了不同延遲的協議。請注意,當您在計算機上運行測試時,頁面加載時間可能會因多種因素而異,例如帶寬,測試時可用的客戶端和服務器資源,等等。如果您想研究更詳盡的測試結果,請參閱文章HTTP/2 –真實的性能測試和分析。最后,如果您想探索如何構建現代Web應用程序,則可以遵循我們的《如何構建現代Web應用程序以使用Django和Ubuntu 18.04上的React來管理客戶信息》教程,或使用以下教程方法設置自己的HTTP/2服務器如何在Ubuntu 16.04上使用HTTP/2支持設置Nginx。
