《高性能网站建设指南》规则4—压缩组件

2019-10-09

如果HTTP请求产生的响应包很小,传输时间就会减少,因为只需要将很小的包从服务器传递到客户端。

从HTTP1.1开始,Web客户端可以通过HTTP请求中的Accept-Encoding头来标识对压缩的支持。

Accept-Encoding: gzip, deflate

如果Web服务器看到请求中有这个头,就会使用客户端列出的方法中的一种来压缩响应。Web服务器通过响应中的Content-Encoding头来通知Web客户端。

Content-Encoding: gzip

gzip是目前最流行和最有效的压缩方法。支持deflate的浏览器也支持gzip,但很多浏览器支持gzip却不支持deflate。

压缩什么

压缩的内容包括XML和JSON在内的任何文本响应,但这里只关注脚本和样式表,因为他们用得最普遍。图片和PDF不应该被压缩,因为它们本来就已经被压缩了,会浪费CPU资源,还可能增加文件的大小。

服务器会花费额外的CPU周期来完成压缩,客户端要对压缩文件进行解压缩。要检测收益是否大于开销,需要考虑响应的大小、连接的带宽和客户端与服务器之间的Internet距离。这些信息难以得到且也有其他变数需要考虑。根据经验通常对1KB或者2KB以上的文件进行压缩。mod_gzip_minimum_file_size指令控制着希望压缩的文件的最小值。

节省

gzip是典型的压缩选择。gzip能将响应整体减少66%,而deflate能减少60%。

配置

Apache1.3使用mod_gzip,以下是最常用的指令: 启用mod_gzip mod_gzip_on 基于文件类型、MIME类型、用户代理等定义哪些需要压缩、哪些不需要。 mod_gzip_item_include mod_gzip_item_exclude 例如明确压缩脚本和样式表: mod_gzip_item_include file .js$ mod_gzip_item_include mime ^application/x-javascript$ mod_gzip_item_include file .css$ mod_gzip_item_include mime ^text/css$

gzip命令行工具提供了一个选项,用于控制压缩的程度,可以在CPU使用量和数据大小的变化之间进行取舍,但mod_gzip中没有配置指令能够控制压缩级别。如果流式压缩产生的CPU负载成问题,可以考虑在磁盘或内存中缓存经过压缩的组件。mod_gzip提供了选项,可以将保存压缩过的内容自动保存在磁盘上,并在原内容发生变化时更新压缩过的内容。使用mod_gzip_can_negotiate和mod_gzip_update_static指令可以完成这一任务。

Apache2.x使用mod_deflate模块。对压缩脚本和样式表的基本配置: AddOutputFilterByType DEFLATE text/html text/css application/x-javascript

和mod_gzip不同,mod_deflate包含了一个用于控制压缩级别的指令——DeflateCompressionLevel。

代理缓存

当浏览器通过代理来发送请求时,情况就变得复杂了。假设某url发送到代理的第一个请求来自于一个不支持gzip的浏览器。这是到达代理的第一个请求,因此缓存为空。代理会将请求转发到web服务器。此时服务器的响应是未经过压缩的。这个没有压缩的响应被代理缓存起来并发送给浏览器。假设到达代理的第二个请求是来自同一个url,来自于一个支持gzip的浏览器。代理会使用缓存中(未经压缩)的内容进行响应,这就失去了进行压缩的机会。如果顺序反了,情况可能更加严重。

解决的方法是在web服务器的响应中添加Vary头,告诉代理根据一个或多个请求头来改变缓存的响应。因此需要在服务器的Vary响应头中包含Accept-Encoding. Vary: Accept-Encoding 默认情况下,mod_gzip会向所有响应添加Vary: Accept-Encoding头。

浏览器边缘情形

不是所有浏览器都完美支持压缩

在Apache1.3可以通过在mod_gzip_item_include中使用恰当的User-Agent值来指定浏览器白名单: mod_gzip_item_include reqheader "User-Agent: MSIE [6-9]" mod_gzip_item_include reqheader "User-Agent: Mozilla/[5-9]"

在Apache2.x使用BrowserMatch指令 BrowserMatch ^MSIE [6-9] gzip BrowserMatch ^Mozilla/[5-9] gzip

将代理缓存加进来,把User-Agent作为代理的另外一种评判标准添加到Vary头中。 Vary: Accept-Encoding,User-Agent mod_gzip检测到你在使用浏览器白名单时,会自动将User-Agent字段添加到Vary头中,不幸的是,由于User-Agent有上千种值,代理不太可能为其所代理的所有url缓存Accept-Encoding和User-Agent的所有组合。甚至这样可能会导致完全禁用为响应包进行的缓存。另外一种方法是使用Vary: 或Cache-Control: private头来禁用代理缓存。因为Vary:头防止了浏览器使用缓存的组件,不过最好使用Cache-Control: private,Google和Yahoo都使用了这种方式。

如何平衡压缩和代理支持的决定是很复杂的,需要在加快响应时间、减小带宽开销和边缘情形浏览器缺陷之间进行权衡。

原文链接:segmentfault.com

上一篇:express-winston
下一篇:vue项目用到的mock数据接口的两种方式
相关教程
关注微信

扫码加入 JavaScript 社区

相关文章

首次访问,需要验证
微信扫码,关注即可
(仅需验证一次)

欢迎加入 JavaScript 社区

号内回复关键字:

回到顶部