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)没有简单的方法来配置它。这种配置通常发生在代理级别。