排查 IIS 6 或 IIS 7.x 中的 IIS 压缩问题
适用于: Internet Information Services 6.0、Internet Information Services 7.0 及更高版本
概述
为 IIS 6 或 7 Web 应用程序启用 HTTP 压缩是提高站点性能的一种方式。
管理员 GUI 不公开完全管理 IIS 所需的许多压缩属性。 它只是提供打开或关闭开关。 因此,若要完全启用 HTTP 压缩,必须使用 IIS 管理器以外的工具来更新 metabase.xml 文件。 最常用的工具是 adsutil.vbs,包含在 IIS 安装目录中。
本文可帮助你配置压缩并识别 IIS 压缩在 IIS 6 和 IIS 7.x 中可能不起作用的常见原因。
此疑难解答中使用的工具
- Fiddler
- 进程监视器
- 元数据库 ACL
- IIS 7 FREB 跟踪
验证
确定压缩是否正常工作
确定 IIS 服务器是否发送压缩响应的唯一方法是分析客户端请求和服务器响应的网络跟踪。 来自客户端的请求必须包含以下 HTTP 请求标头:
HTTP: Accept-Encoding =gzip, deflate
这让服务器知道客户端愿意接收压缩的响应并支持压缩。 返回时,来自服务器的压缩响应将包含以下 HTTP 响应标头和值:
HTTP: Content-Encoding = gzip
以下屏幕截图显示了压缩不起作用时 Fiddler 工具的输出:
排查压缩问题
执行以下步骤来排查压缩问题:
在 IIS 6 或 IIS 7 中启用压缩。
在 IIS 管理器中,右键单击 “网站 ”节点,选择“ 属性”,然后选择“ 服务”。
指定压缩文件夹和权限。
IIS 将压缩文件存储在可以配置的文件夹中。 默认情况下,它
%windir%\IIS Temporary Compressed Files
适用于 IIS 6 和%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files
IIS 7。IIS_WPG(对于 IIS 7 为 IIS_IURS)必须对此文件夹具有完全控制权限。 使用 进程监视器 排查此类权限问题。
检查是否在Metabase.xml中启用了压缩。
在右侧节点的元数据库中未打开压缩。 压缩配置有三个元数据库节点:
w3svc/filters/compression/parameters
w3svc/filters/compression/gzip
w3svc/filters/compression/deflate
配置
/parameters
节点是必需的。 然后,可以配置或/gzip
/deflate
同时配置节点或两者。 这意味着仅配置 gzip、deflate 或参数节点将不起作用。 如果配置/parameters
和/gzip
节点,将启用 Gzip 压缩方案。 如果配置/parameters
和/deflate
节点,将启用 Deflate 压缩方案。 最后,如果配置所有三个节点,将启用 GZip 压缩和 Deflate 压缩。检查 IIS 6 的元数据库权限。
默认情况下,
IIS_WPG
具有读取、不安全读取、枚举密钥和写入/LM/W3SVC/Filters
权限。如果由于意外更改或安全强化而删除了权限,IIS 将无法初始化压缩。
使用 metaacl.vbs 验证和修改 IIS 6 元数据库 ACL。 有关详细信息,请参阅 默认元数据库 ACL。
如果应用程序池标识(或
IIS_WPG
一般情况下的组)对元数据库密钥 W3SVC 或筛选器没有读取和写入访问权限,则会在适用于 Windows 的企业跟踪(ETW)跟踪中记录失败情况COMPRESSION_DISABLED
。ETW 跟踪
IISCompression: STATIC_COMPRESSION_NOT_SUCCESS - IIS has been unsuccessful doing static compression Reason: COMPRESSION_DISABLED
检查是否在Metabase.xml中关闭动态或静态压缩。
在三个配置节点(
/parameters
/gzip
和/deflate
)中,可以选择启用静态和/或动态压缩。 若要为文件类型(如.txt和.html)启用静态压缩,必须将密钥设置为HcDoStaticCompression
1
(或TRUE
)。 若要为文件类型(如 .asp、.aspx、.asmx 或 .exe)启用动态压缩,必须将密钥设置为HcDoDynamicCompression
1
(或TRUE
)。例如,若要在
/parameters
节点上设置动态压缩,请使用 adsutil.vbs 运行以下命令:cscript.exe adsutil.vbs SET w3svc/filters/compression/parameters/HcDoDynamicCompression TRUE
上一命令的输出如下所示:
HcDoDynamicCompression : (BOOLEAN) True
在 IIS7 中
<system.webServer> <urlCompression doStaticCompression="true" doDynamicCompression="true" /> </system.webServer>
检查要压缩的文件类型是否在节点的
/gzip
/deflate
相应“文件扩展名”部分中列出。使用
HcDoDynamicCompression
和/或HcDoStaticCompression
键启用压缩后,请指定必须实际压缩哪些文件类型。 默认情况下,STATIC 压缩使用文件类型,例如.htm、.html和.txt,动态压缩使用.asp、.dll和.exe。 如果要压缩不同的文件类型(例如.aspx),请根据所使用的压缩类型,将其添加到和或/deflate
节点中的/gzip
相应文件扩展名部分。 对于静态文件压缩(如 .html、txt 和 xml),请将文件扩展名添加到HcFileExtensions
属性。 对于动态压缩(如.asp、.aspx和 .asmx),请将其添加到HcScriptFileExtension
属性。对于静态文件
adsutil.vbs SET w3svc/filters/compression/gzip/HcFileExtensions "htm" "html" "txt"
adsutil.vbs GET w3svc/filters/compression/gzip/HcFileExtensions
上一个命令显示以下输出:
HcFileExtensions : (LIST) (3 Items) "htm" "html" "txt"
对于动态文件
adsutil.vbs SET w3svc/filters/compression/gzip/HcScriptFileExtensions "asp" "dll" "exe" "aspx" adsutil.vbs get w3svc/filters/compression/gzip/HcScriptFileExtensions
上一个命令显示以下输出:
HcFileExtensions : (LIST) (4 Items) "asp" "dll" "exe" "aspx"
在 IIS7 中
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" minFileSizeForComp="1000"> <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" /> <staticTypes> <add mimeType="text/*" enabled="true" /> <add mimeType="message/*" enabled="true" /> <add mimeType="application/x-javascript" enabled="true" /> <add mimeType="application/atom+xml" enabled="true" /> <add mimeType="application/xaml+xml" enabled="true" /> <add mimeType="*/*" enabled="false" /> </staticTypes> <dynamicTypes> <add mimeType="text/*" enabled="true" /> <add mimeType="message/*" enabled="true" /> <add mimeType="application/x-javascript" enabled="true" /> <add mimeType="*/*" enabled="false" /> </dynamicTypes> </httpCompression> <system.web.extensions> <scripting> <scriptResourceHandler enableCompression="false" /> </scripting> </system.web.extensions>
注意
必须使用正确的语法配置
HcFileExtensions
或HcScriptFileExtensions
属性。 任何尾随空格或不必要的引号或回车将导致属性配置错误。 遗憾的是, 如果添加额外的空间,adsutil.vbs 不会显示错误,因此需要非常小心。 此外,不能将值复制或粘贴到命令提示符或 metabase.xml 文件(元数据库直接编辑)中,并且必须手动键入它。检查是否在主级别设置压缩,但正在由子级别的设置重写。
将在级别启用
w3svc/filters/compression
压缩。 但是,可能是通过网站或应用程序级别的设置来替代它。例如,如果已
HcDoDynamicCompression
设置为w3svc/filters/compression
TRUE
级别,并且对于默认网站已DoDynamicCompression
设置为FALSE
,则不会发生对默认网站的请求的响应的动态压缩。检查防病毒程序是否已扫描保存压缩文件的目录。
在运行 IIS 的服务器上启用压缩并从 IIS 压缩目录中提供 HTTP 请求时,可能会返回 0 字节文件,而不是预期的文件。
注意
仅当启用 HTTP 静态压缩时,才会出现这些症状。
发生这种情况是因为 IIS 服务器上运行的防病毒软件正在扫描 IIS 压缩目录。
因此,需要从防病毒软件的扫描列表中排除 IIS 压缩目录。
检查所请求的 URL 是否包含斜杠,作为传递给执行 DLL 文件的参数的一部分。
检查 ISAPI 筛选器是否修改请求或响应标头。
ISAPI 正在执行发送操作,并且不会将完整的 HTTP 标头集与实体一起发送到
HTTP_COMPRESSION::DoDynamicCompression
。 由于DoDynamicCompression
不会从 ISAPI 接收所有数据,因此无法压缩响应。 第三方和/或非Microsoft ISAPIs 通过将标头放入用于实体正文的函数中或用于 HTTP 标头的函数中的实体正文,或者未提供任何标头来执行此操作。 发生这种情况时,ISAPI 筛选器 SF_NOTIFY_SEND_RESPONSE、AddResponseHeaders 或动态压缩等操作都将失败。 ISAPI 需要将标头和实体分别放置在正确的位置。检查响应状态代码是否为 200 以外的代码。 在 IIS 6 或 7 中,只有具有 HTTP 200 状态的响应才会压缩。
不会压缩包含 200 以外的状态代码的响应。 必须编写一个
HTTPModule
实现相同的操作。检查请求是否包含一个
Via: header
,指示Via headers
请求是通过代理传入 IIS 的。许多代理无法正确处理压缩标头,并且不应向客户端提供压缩数据。 因此,默认情况下,当请求具有 Via 标头时,不允许压缩响应。 可以通过将
HcNoCompressionForProxies
元数据库密钥设置为True
..检查请求是否为静态页面,响应是否包含文档页脚。 文档页脚将导致静态压缩失败。
检查静态压缩是否正常工作。 如果在 IIS 中的根级别安装了通配符应用程序映射,则可能发生这种情况。 例如,我们在服务器上具有.html或.txt扩展的应用程序映射,这会使 IIS 将 .txt请求视为动态请求而不是静态请求,并且由于.txt不是动态压缩列表中的扩展,因此它不会被压缩。
检查 IIS 压缩和
Accept-Encoding: identity
字段是否存在。根据RFC2616,如果
Accept-Encoding
请求中存在字段,并且服务器无法发送响应(根据Accept-Encoding
标头可接受),则服务器应使用 406(不可接受)状态代码发送错误响应。 如果请求中不存在Accept-Encoding
任何字段,服务器可能会假定客户端将接受任何内容编码。 在这种情况下,如果“identity”是可用的内容代码之一,则服务器应使用“标识”内容代码,除非它具有其他信息,即不同的内容代码对客户端有意义。检查是否使用 ETW 跟踪来排查 IIS 压缩问题。
Windows 事件跟踪(ETW)是 Windows OS 的一项功能,可用于排查 HTTP 请求的问题。
下面是排查 IIS 压缩问题的步骤。
创建名为 IISProviders.txt 的文本文件,并将关注内容放入文件中。IIS:WWW Server“是提供程序名称,0xFFFFFFFE表示所有事件的跟踪,5 表示详细级别。
打开命令提示符,并运行以下命令。
logman start trace compressionTrace -pf IISProviders.txt -ets
再现此问题。
运行以下命令以停止跟踪。
logman stop trace compressionTrace -ets
将跟踪转换为文本文件。
跟踪报表将二进制跟踪数据转换为文本,并在执行
tracerpt
命令的目录中生成两个文件:tracerpt compressionTrace.etl
Summary.txt 包含有关跟踪会话的一般详细信息,包括使用了哪些提供程序。
DumpFile.csv 包含文本格式的实际跟踪数据。
读取跟踪文件以查找有用的信息。 打开 dumpfile.csv,找到COMPRESSION_NOT_SUCCESS等关键字。 下面是一个示例:
IISCompression, STATIC_COMPRESSION_NOT_SUCCESS, 0x000008B0, 129744354075770195, 0, 0, {00000000-0000-0000-0700-0060000000bd}, "NO_MATCHING_SCHEME", 0, 0
此错误NO_MATCHING_SCHEME意味着此扩展或 Accept-Encoding 没有压缩方案匹配。 有关压缩错误的详细列表,请参阅 压缩错误列表。
检查是否使用了 FREB 跟踪来排查 IIS 压缩问题。
有关详细步骤,请参阅 在 IIS 7 中使用跟踪排查失败的请求。
下面是使用 IIS 7 FREB 跟踪排查压缩问题的示例。
压缩错误列表
有关压缩错误的详细列表,请参阅下表。
注意
以下原因适用于 IIS 6 和 IIS 7。
Reason | 说明 |
---|---|
NO_ACCEPT_ENCODING | 客户端不发送接受编码。 |
COMPRESSION_DISABLED | 压缩被禁用,因为找不到合适的配置。 |
NO_COMPRESSION_10 | 服务器未配置为压缩 1.0 请求。 |
NO_COMPRESSION_PROXY | 服务器未配置为压缩代理请求。 |
NO_MATCHING_SCHEME | 此扩展/Accept-Encoding 没有压缩方案匹配。 |
UNKNOWN_ERROR | 未知错误。 |
NO_COMPRESSION_RANGE | 服务器未配置为压缩范围请求 |
FILE_TOO_SMALL | 小于压缩阈值的文件。 |
FILE_ENCRYPTED | 文件已加密。 |
COMPRESS_FILE_NOT_FOUND | 压缩副本不存在。 |
COMPRESS_FILE_STALE | 压缩副本已过期。 |
NO_MATCHING_CONTENT_TYPE | 服务器未配置为压缩此扩展的内容类型。 |
HEADERS_SENT_TWICE | 为同一响应发送两次标头。 |
NO_HEADER_SENT | 实体正文发送之前未发送标头。 |
NOT_SUCCESS_STATUS | 响应状态代码未成功(200)。 |
ALREADY_CONTENT_ENCODING | 响应中已存在内容编码。 |
注意
以下原因仅适用于 IIS 7。
Reason | 说明 |
---|---|
FOOTER_ENABLED | 为静态文件启用文档页脚。 |
NOT_FREQUENTLY_HIT | URL 尚未频繁请求,无法证明压缩是正当的。 |
FAIL_TO_COMPRESS | 无法创建压缩副本。 |