充分利用 IIS 压缩 - 第一部分:配置 IIS 7 压缩






4.86/5 (29投票s)
在本系列的两篇文章中,我将展示如何充分利用 IIS 7 和 IIS 6 内置的压缩功能。第一篇文章将重点介绍 IIS 7。
系列文章
- 充分利用 IIS 压缩 - 第一部分:配置 IIS 7 压缩
- 充分利用 IIS 压缩 - 第二部分:配置 IIS 6 压缩
引言
使用压缩是缩短页面加载时间最有效的方法。服务器发送到浏览器的 .aspx 文件包含 HTML。HTML 可以被 gzip 等算法高度压缩。因此,现代 Web 服务器(包括 IIS 5 及更高版本)都具备压缩传出文件的能力,而现代浏览器也具备解压缩传入文件的能力。
IIS 6 和 IIS 7 都提供了高级的压缩相关选项,可帮助您为网站带来更好的性能提升,并更好地利用您的服务器和带宽。然而,这些选项并非总是易于访问。本系列文章将分步展示如何解锁这些选项。
在本系列的第一篇文章中,我们将重点介绍 IIS 7 的压缩配置。如果您习惯使用 IIS 6,您会发现 IIS 7 提供了许多新功能,包括缓存压缩后的静态文件以及压缩后的动态文件的能力。如果您仍在使用 IIS 6,系列文章的 下一篇文章 将介绍如何配置 IIS 6 压缩。
本文基于我著作《ASP.NET Site Performance Secrets》的第 10 章《压缩》。
如果您喜欢这篇文章,请 投票支持。
目录
- 与压缩相关的请求和响应标头
- IIS 7 压缩的起始配置
- 安装动态内容压缩模块
- 启用压缩
- 按网站、文件夹或文件设置压缩
- 压缩级别
- 基于 CPU 使用率禁用压缩
- 设置静态压缩的请求频率阈值
- 缓存压缩的动态文件
- 提高页面的可压缩性
- 摘要
与压缩相关的请求和响应标头
服务器如何知道浏览器可以接受压缩内容?浏览器又如何知道它收到的内容是压缩过的?
当支持压缩的浏览器向服务器发送请求时,它会包含一个名为 Accept-Encoding 的请求标头,告知服务器它支持哪些压缩算法。例如:
Accept-Encoding: gzip,deflate
如果服务器随后对响应进行了压缩,它会在(未压缩的)文件标头中包含 Content-Encoding 响应标头,说明文件是如何被压缩的,如下所示:
Content-Encoding: gzip
这样可以使浏览器和服务器在压缩方面保持同步。然而,发送和接收请求和响应的不仅是浏览器和服务器,还有代理服务器。代理服务器可以缓存响应并将后续请求从其缓存中提供。当代理服务器缓存压缩文件时,我们如何确保代理服务器不会将该压缩文件发送给无法处理压缩文件的浏览器呢?
IIS 6 和 IIS 7 采用的解决方案是,在服务器响应中发送一个 Vary 标头(当启用压缩时),以告知代理服务器:如果它收到一个没有 Accept-Encoding 请求标头的请求,它就不能提供响应于带有 Accept-Encoding 请求标头的请求而发送的文件,反之亦然,也就是说,Accept-Encoding 请求标头必须匹配。IIS 6 和 7 通过发送 Vary 标头来实现这一点,如下所示:
Vary: Accept-Encoding
IIS 6 还允许您通过其元数据库中的属性来覆盖压缩文件的 Cache-Control 和 Expires 标头。这允许您抑制压缩文件的代理缓存。IIS 6 元数据库将在 第二部分(关于配置 IIS 6 压缩)中进行介绍。用于覆盖 Cache-Control 和 Expires 标头的元数据库属性可以在 此处 找到。
IIS 7 压缩的起始配置
在开始配置 IIS 7 压缩之前,请访问以下网站,了解您的页面是否已使用压缩,以及如果使用,您节省了多少带宽:
在 IIS 7 中启用压缩基本上包含以下步骤:
- 安装动态内容压缩模块;
- 启用压缩;
- 配置高级功能。
让我们一步一步地进行。
安装动态内容压缩模块
如果您想对动态文件使用压缩,请首先安装动态内容压缩模块。具体步骤取决于您使用的是 Vista/Windows 7 还是 Windows Server 2008。
在 Windows Server 2008 上
- 单击 开始 | 管理工具 | 服务器管理器。
- 在左侧,展开 角色,然后单击 Web 服务器 (IIS)。
- 向下滚动到 角色服务 部分,然后单击 添加角色服务。将打开 添加角色服务 向导。
- 在 选择角色服务 页面上,向下滚动到 性能 部分,然后选择 动态内容压缩。单击 下一步。
- 阅读消息,然后单击 安装。
- 安装完成后,关闭向导。
在 Vista 或 Windows 7 上
- 单击 开始 | 控制面板 | 程序 | 启用或关闭 Windows 功能。将打开 Windows 功能 对话框。
- 展开 Internet 信息服务,展开 万维网服务,然后展开 性能功能。选择 HTTP 压缩动态。
- 单击 确定。等待功能配置完成。
启用压缩
现在在 IIS 管理器中启用压缩。
- 打开 IIS 管理器。单击 开始 | 控制面板。在搜索框中键入 admin。单击 管理工具。双击 Internet Information Services (IIS) Manager。
- 单击您的计算机。然后双击右侧的 压缩 图标。
- 将打开压缩窗口。您可以在此处为动态内容和静态内容启用压缩。窗口显示以下项目:
- 启用动态内容压缩:除非您的服务器已经使用大量 CPU,否则您需要启用动态内容压缩。
- 启用静态内容压缩:您可以安全地启用静态内容压缩,因为压缩后的静态内容会被缓存。因此,只有初始压缩会占用 CPU 周期。
- 仅压缩大于 (字节) 的文件:不压缩小文件是明智的。因为压缩会产生一些文件开销,压缩小文件实际上可能会使其变大而不是变小。
- 缓存目录:这是存储压缩后静态文件的位置。如果您在系统驱动器上磁盘空间不足,请考虑将其放在另一个驱动器上。确保该驱动器是本地驱动器或 NTFS 分区,并且未被压缩或共享。
- 每个应用程序池磁盘空间限制 (MB):如果您有很多应用程序池但磁盘空间有限,您可能需要调整此设置。如果您有 100 个应用程序池,并且将此设置为 100MB,则可能会使用 100 x 100MB = 10GB 来缓存静态压缩文件。
- 在窗口的右侧,单击 应用。现在已启用压缩。
按网站、文件夹或文件设置压缩
除了为服务器上的所有网站启用或禁用压缩外,您还可以在网站级别,甚至文件夹或文件级别启用或禁用压缩。
要实现此目的:
- 打开 IIS 管理器,然后在左侧,单击您想要更改其压缩状态的网站、文件夹或文件。
- 确保中间窗格已切换到 功能视图,然后双击 压缩 图标。
- 这将打开一个窗口,您可以在其中为动态或静态文件启用或禁用压缩。
压缩级别
您可以通过设置压缩级别来调整压缩与 CPU 使用率之间的权衡。压缩级别越高,压缩和 CPU 使用率就越高。
压缩级别可以分别为静态文件和动态文件设置。对于静态文件,请使用 9,这是最高级别。对于动态文件,根据 这项研究,压缩级别 4 似乎是一个最佳选择。
但是,您的网站的最佳压缩级别可能有所不同,具体取决于您有多少可用 CPU 容量、页面的可压缩性以及您的带宽成本。尝试不同的级别,看看哪个最适合您。
要设置压缩级别:
- 从命令提示符执行此操作:
- 重置 IIS 服务器以使新的压缩级别生效。在 IIS 管理器中,单击树顶部的服务器,然后单击右侧的 重新启动。
C:\Windows\System32\Inetsrv\Appcmd.exe
set config -section:httpCompression
-[name='gzip'].staticCompressionLevel:9
-[name='gzip'].dynamicCompressionLevel:4
(这会将静态文件的压缩级别设置为 9,动态文件的压缩级别设置为 4。)
基于 CPU 使用率禁用压缩
为确保压缩不会使 CPU 过载,IIS 7 每 30 秒计算一次平均 CPU 使用率。当 CPU 使用率超过给定限制时,它会自动关闭压缩。然后,当 CPU 使用率降至第二个限制以下时,它会重新打开压缩。
这些限制的默认值为:
CPU 使用率达到以下值时关闭压缩 | CPU 使用率达到以下值时重新打开压缩 | |
---|---|---|
动态文件 | 90% | 50% |
静态文件 | 100% | 50% |
请注意,这意味着,如果您的服务器 CPU 使用率持续高于 50%,并在达到 90% 时出现峰值,动态文件的压缩将被关闭,但将永远不会重新打开。
您可以通过修改 applicationHost.config 文件来更改这些限制,该文件通常位于 C:\Windows\System32\inetsrv\config 文件夹中。
- 备份 applicationHost.config 文件。
- 使用文本编辑器打开 applicationHost.config。
- 找到
<httpCompression>
部分。 - 要将动态文件压缩重新打开的 CPU 使用率更改为 70%,请将
dynamicCompressionEnableCpuUsage
属性添加到httpCompression
元素,如下所示: - 保存 applicationHost.config 文件。
- 重置 IIS 服务器以使新的压缩级别生效。在 IIS 管理器中,单击树顶部的服务器,然后单击右侧的 重新启动。
<httpCompression dynamicCompressionEnableCpuUsage="70" .... >
请注意,您向属性提供的是一个数字,而不是百分比,因此在设置属性时不要写百分号。此处显示的 70 值仅为示例,并非建议。您需要确定适合您自己网站的最佳值。
如果您想更改任何其他限制,以下是匹配的属性:
CPU 使用率达到以下值时关闭压缩 | CPU 使用率达到以下值时重新打开压缩 | |
---|---|---|
动态文件 | dynamicCompressionDisableCpuUsage |
dynamicCompressionEnableCpuUsage |
静态文件 | staticCompressionDisableCpuUsage |
staticCompressionEnableCpuUsage |
如果您想阻止 IIS 根据 CPU 使用率关闭压缩,请将所有这些属性设置为 100。
您可以在 此处 找到可与 httpCompression
一起使用的所有元素和属性。
设置静态压缩的请求频率阈值
正如您之前所见,IIS 7 会缓存静态文件的压缩版本。因此,如果收到对已压缩版本已缓存的静态文件的请求,则无需再次压缩。
但是,如果缓存中没有压缩版本呢?IIS 7 会立即压缩该文件并将其放入缓存吗?答案是肯定的,但前提是该文件被频繁请求。通过不压缩仅被请求不频繁的文件,IIS 7 节省了 CPU 使用率和缓存空间。
默认情况下,如果一个文件在 10 秒内被请求两次或更多次,则认为它被频繁请求。这由 web.config 中 serverRuntime
元素中的两个属性决定:
serverRuntime 属性 | 描述 |
---|---|
frequentHitThreshold |
URL 在 frequentHitTimePeriod 属性指定的时段内必须被请求的次数,才能被视为频繁命中。必须介于 1 和 2147483647 之间。默认为 2。 |
frequentHitTimePeriod
|
URL 在 frequentHitThreshold 属性指定的次数之前必须被请求的时间间隔,之后才被视为频繁命中。默认为 10 秒。 |
这意味着,当一个静态文件首次被请求时,它不会被压缩。
例如,要指定静态文件在 15 秒内需要被命中七次才会被压缩,请使用:
<configuration>
...
<system.webServer>
<serverRuntime frequentHitThreshold="7" frequentHitTimePeriod="00:00:15" />
</system.webServer>
...
</configuration>
缓存压缩的动态文件
您已经看到 IIS 7 只缓存静态文件的压缩版本,并且动态文件会为每个请求进行压缩(前提是启用了动态文件压缩)。这意味着压缩动态文件比静态文件消耗更多的 CPU。
如果动态文件对每个访问者都不同,例如,如果每个页面都包含个人信息,这样做是有意义的。然而,如果动态页面相当静态且对所有访问者都相同,那么缓存它们的压缩版本也是有意义的。
您可能已经使用 ASP.NET OutputCache
指令来缓存您的 .aspx 页面。问题是,默认情况下,IIS 将未压缩的文件版本存储在输出缓存中,而不是压缩版本。对于每个请求,IIS 然后必须压缩缓存的内容,然后将其发送到浏览器。这效率不高。
将压缩文件存储在输出缓存中
以下是如何让 IIS 缓存文件的压缩版本而不是未压缩版本。这样,它不必为每个请求压缩文件,从而减少 CPU 使用率。
由于这使用了 ASP.NET 输出缓存,因此您需要在页面中使用 OutputCache
指令,如下所示:
<%@ OutputCache Duration="300" VaryByParam="none" %>
这将缓存页面 300 秒。
现在,为了让 IIS 缓存压缩版本而不是未压缩版本,请修改 applicationHost.config 文件。您通常会在 C:\Windows\System32\inetsrv\config 文件夹中找到此文件。
- 备份 applicationHost.config 文件。
- 使用文本编辑器打开 applicationHost.config。
- 找到
<urlCompression>
部分。 - 将
dynamicCompressionBeforeCache="true"
属性添加到urlCompression
元素,如下所示: - 保存 applicationHost.config 文件。
- 重置 IIS 服务器以使新属性生效。
- 在 IIS 管理器中,单击树顶部的服务器,然后单击右侧的 重新启动。
<urlCompression dynamicCompressionBeforeCache="true" ... />
如果客户端不接受压缩内容怎么办?
现在我们已经缓存了压缩内容,如果有人使用不支持压缩的浏览器访问您的网站,会发生什么情况?
为了模拟这种情况,让我们向服务器发送一个没有 Accept-Encoding 请求标头的请求。这应该会迫使服务器发送未压缩的内容。
为此,我们将使用 Fiddler,一个免费的代理,它允许您在请求和响应在浏览器和服务器之间传输时进行“修改”。使用 Firefox 最容易做到这一点。
- 打开 Firefox 并从 http://www.fiddler2.com/fiddler2/ 下载 Fiddler。
- 安装 Fiddler 并启动它。
- 在 Firefox 状态栏上,启用将流量强制到 Fiddler。
- 此时,当您使用 Firefox 访问页面时,服务器仍应使用压缩(假设请求具有允许 gzip 压缩的 Accept-Encoding 请求标头)。
- 使用 Firefox,访问 http://chrispederick.com/work/web-developer 下载并安装 Web Developer 附加组件。
- 安装 Web Developer 后,再次加载页面。
- 在页面任意位置右键单击。将出现一个弹出菜单。单击 Web Developer | Information | View Document Size。将出现一个新窗口,显示构成页面的文件组。
- 展开 Documents 组以查看页面大小。如果在 Internet 上传输时进行了压缩,您还将看到其压缩大小。
- 现在,让 Fiddler 从从 Firefox 到 Web 服务器的请求中删除 Accept-Encoding 请求标头。在 Fiddler 窗口的右侧,单击 Filters 选项卡,选择 Use Filters,选择 Delete request header,然后输入 Accept-Encoding。
- 在 Firefox 中刷新页面。使用 Web Developer 再次检查文件大小。您应该会发现此请求未使用任何压缩。这会让不支持压缩的浏览器满意。到目前为止,一切顺利。
- 在 Fiddler 中,取消选中 Delete request header 复选框。结果,Accept-Encoding 请求标头现在可以再次到达 Web 服务器。
- 刷新页面。服务器现在应该会再次压缩文件。但是,如果您使用 Web Developer 检查,您会发现它仍然以未压缩的方式发送文件!
- 您可以通过在
OutputCache
指令中包含VaryByContentEncoding
来防止这种情况发生,如下面的代码所示: - 如果您现在删除 Accept-Encoding 标头,然后再次通过,您将看到服务器始终向接受压缩内容的客户端发送压缩内容,即使另一个客户端不接受。
- 在您结束此实验并关闭 Fiddler 之前,请返回 Firefox 状态栏,停止将流量发送到 Fiddler。否则,当您关闭 Fiddler 时,Firefox 会抱怨缺少代理。
您可以使用 Firefox 的 Web Developer 附加组件来测量您的压缩页面在 Internet 上传输到浏览器时的实际大小。
这是因为当 IIS 收到未压缩内容的请求时,它会丢弃缓存中的压缩内容,重新生成内容,并以未压缩的形式将其存储在缓存中。然后,它会一直提供这些未压缩的内容,直到缓存过期,即使是发送给接受压缩内容的客户端也是如此。
<%@ OutputCache Duration="300" VaryByParam="none"
VaryByContentEncoding="gzip;deflate" %>
在 OutputCache
指令中使用 VaryByContentEncoding
的一个缺点是它会禁用该文件的 内核缓存。内核缓存是一种非常高效的服务器端缓存形式,并在我的著作《ASP.NET Site Performance Secrets》的第 5 章中进行了讨论。
那么,您应该在 OutputCache
指令中使用 VaryByContentEncoding
吗?考虑到您正在阅读本章,使用 VaryByContentEncoding
带来的压缩增益可能超过内核缓存的损失,尤其是在您已经使用输出缓存的情况下。您最好的选择是在生产环境中尝试这两种场景一段时间,并比较每种场景下的 CPU 使用率、响应时间和每个请求使用的带宽。
提高页面的可压缩性
如果您的服务器使用压缩,那么优化您的 .aspx、JavaScript 和 CSS 文件的可压缩性是有意义的。像重复内容这样的压缩算法,对一致性要求很高。
- 始终以相同的顺序指定 HTML 属性。实现这一点的一种方法是让所有 HTML 都由高级 Web 控件和自定义服务器控件生成,而不是低级 HTML 服务器控件。这将稍微增加 CPU 使用率,但会确保一致性。例如,编写以下内容:
<asp:Hyperlink runat="server"......>
而不是
<a runat="server"......>
总结
在本文中,我们了解了如何在 IIS 7 上配置压缩,包括其更高级、鲜为人知的功能。在下一篇文章中,我将介绍如何最大限度地利用 IIS 6 内置的压缩功能。
如果您喜欢本系列,并想了解有关如何提高 ASP.NET 网站性能的完整故事,从数据库服务器到 Web 服务器再到浏览器,请考虑我的著作《ASP.NET Site Performance Secrets》。或访问我的网站 ASP.NET Performance。