HTTP 中的壓縮

壓縮是提高網站效能的重要方法。對於某些文件,檔案大小減少高達 70% 會降低對頻寬容量的需求。多年來,演算法也變得更加高效,並且客戶端和伺服器支援了新的演算法。

實際上,Web 開發人員無需實現壓縮機制,瀏覽器和伺服器已經實現了它,但他們必須確保伺服器配置得當。壓縮發生在三個不同的級別

  • 首先,一些檔案格式使用特定的最佳化方法進行壓縮,
  • 然後,通用加密可以在 HTTP 級別進行(資源從端到端壓縮傳輸),
  • 最後,可以在 HTTP 連線的兩個節點之間定義連線級別的壓縮。

檔案格式壓縮

每種資料型別都有一些冗餘,即浪費的空間。如果文字通常可以具有高達 60% 的冗餘,那麼對於音訊和影片等其他一些媒體來說,此比率可能更高。與文字不同,這些其他媒體型別使用大量空間來儲存其資料,並且在很早的時候就明顯需要最佳化儲存並重新獲得空間。工程師設計了專門為此目的設計的特定檔案格式使用的最佳化壓縮演算法。用於檔案的壓縮演算法可以分為兩大類

  • 無失真壓縮,其中壓縮-解壓縮週期不會改變恢復的資料。它與原始資料(位元組對位元組)匹配。對於影像,gifpng 使用無失真壓縮。
  • 有失真壓縮,其中週期以使用者(希望)不可察覺的方式改變原始資料。Web 上的影片格式是有損的;jpeg 影像格式也是有損的。

一些格式可以用於無失真壓縮或有失真壓縮,例如webp,通常有損演算法可以配置為壓縮更多或更少,這當然會導致質量降低或提高。為了提高網站的效能,最好儘可能地壓縮,同時保持可接受的質量水平。對於影像,由工具生成的影像可能未針對 Web 進行了足夠最佳化;建議使用盡可能壓縮並保持所需質量的工具。有許多專門用於此目的的工具

有失真壓縮演算法通常比無失真壓縮演算法更有效。

注意:由於壓縮對特定型別的檔案效果更好,因此通常不會提供任何方法來第二次壓縮它們。事實上,這通常適得其反,因為開銷成本(演算法通常需要一個字典,這會增加初始大小)可能高於壓縮帶來的額外增益,從而導致檔案更大。不要將以下兩種技術用於壓縮格式的檔案。

端到端壓縮

對於壓縮,端到端壓縮是網站效能改進最大的地方。端到端壓縮指的是伺服器對訊息主體進行壓縮,並且壓縮在到達客戶端之前保持不變。無論中間節點是什麼,它們都不會觸碰主體。

A server sending a compressed HTTP body to a client via network nodes. The body is not decompressed at any hop through the network until it reaches the client.

所有現代瀏覽器和伺服器都支援它,唯一要協商的是要使用的壓縮演算法。這些演算法針對文字進行了最佳化。在 1990 年代,壓縮技術正在快速發展,並且許多連續的演算法已新增到可能的選項集中。如今,只有兩個是相關的:gzip(最常見的)和br(新的挑戰者)。

為了選擇要使用的演算法,瀏覽器和伺服器使用主動內容協商。瀏覽器傳送一個Accept-Encoding 標頭,其中包含它支援的演算法及其優先順序順序,伺服器選擇一個,用它來壓縮響應的主體並使用Content-Encoding 標頭告訴瀏覽器它選擇的演算法。由於內容協商已被用於根據其編碼選擇表示,因此伺服器必須傳送一個包含至少Accept-EncodingVary 標頭,以及響應中的此標頭;這樣,快取就能快取資源的不同表示。

A client requesting content with an 'Accept-Encoding: br, gzip' header. The server responds with a body compressed using the Brotli algorithm and the required 'Content-Encoding' and 'Vary' headers.

由於壓縮帶來了顯著的效能改進,因此建議為所有檔案啟用它,除了已壓縮的檔案(如影像、音訊檔案和影片)。

Apache 支援壓縮並使用mod_deflate;對於 Nginx,有ngx_http_gzip_module;對於 IIS,有<httpCompression> 元素。

逐跳壓縮

逐跳壓縮雖然與端到端壓縮類似,但在一個基本元素上有所不同:壓縮不是在伺服器上的資源上進行的,而是建立了一個特定的表示,然後進行傳輸,而是在客戶端和伺服器之間路徑上的任何兩個節點之間的訊息主體上進行的。連續中間節點之間的連線可能會應用不同的壓縮。

A server sending an uncompressed HTTP body to a client via network nodes. The body is compressed and decompressed by nodes on the network depending on 'Transfer-Encoding' headers before it reaches the client.

為此,HTTP 使用了類似於端到端壓縮內容協商的機制:傳輸請求的節點使用TE 標頭來宣傳其意願,而另一個節點選擇適當的方法,應用它並使用Transfer-Encoding 標頭指示其選擇。

A client requesting content from a server with no compression-related headers. The server responds with an uncompressed body. The body is compressed and decompressed by nodes on the network before it reaches the client.

實際上,逐跳壓縮對於伺服器和客戶端是透明的,並且很少使用。TETransfer-Encoding 主要用於以塊的形式傳送響應,允許在不知道資源長度的情況下開始傳輸資源。

請注意,在跳躍級別使用Transfer-Encoding 和壓縮非常少見,以至於大多數伺服器(如 Apache、Nginx 或 IIS)沒有簡單的方法來配置它。這種配置通常發生在代理級別。