排查 IIS6/IIS7.x 中的 IIS 压缩问题

作者:Shoeb Ilyas Bhaldar 和 Mike Laing

此疑难解答中使用的工具:

  • Fiddler
  • 网络监视器
  • 进程监视器
  • 元数据库 ACL
  • IIS 6 ETW 跟踪
  • IIS 7 FREB 跟踪

此材料仅供参考。 Microsoft 不做任何明示或暗示的担保。

概述

为 IIS6/7 Web 应用程序启用 HTTP 压缩是提高站点性能的一种方式。

遗憾的是,IIS 管理员 GUI 不会公开完全管理它所需的许多压缩属性。 它只允许我们打开或关闭它。 因此,请务必注意,若要将其完全配置为 http 压缩,需要使用 IIS 管理器以外的工具编辑metabase.xml。 我们使用的最常用工具是adsutil.vbs,该工具包含在 IIS 安装中

此疑难解答将帮助你配置压缩,确定 IIS 压缩 & 在 IIS6 和 IIS 7.x 中可能不起作用的常见原因

验证

确定压缩是否正常工作

确定 IIS 服务器是否发送压缩响应的唯一方法是分析客户端请求/服务器响应的网络跟踪。 来自客户端的请求需要包含以下 HTTP 请求标头:

HTTP: Accept-Encoding =gzip, deflate

这会告知服务器客户端支持压缩,并接受压缩的响应。 返回时,来自服务器的压缩响应将包含以下 HTTP 响应标头和一个值:

HTTP: Content-Encoding = gzip

压缩不起作用时 Fiddler 输出:

“转换器”选项卡中的“H T T P 压缩”设置为“无压缩”的屏幕截图。

“转换器”选项卡中禁用的 H T T P 压缩部分的屏幕截图。

疑难解答

  1. 在 IIS6/IIS7 中启用压缩: 在 IIS 管理器中,右键单击网站节点“属性”,然后单击“服务”。

    选中“压缩静态文件”和“最大临时目录大小”设置为“无限制”的 H T T P 压缩的屏幕截图。

    启用的压缩选项的屏幕截图,其中包含默认值。

  2. 压缩文件夹及其权限: IIS 将压缩文件存储在可以配置的文件夹中。 默认情况下,它 %windir%\IIS Temporary Compressed Files 适用于 IIS 6 和 %SystemDrive%\inetpub\temp\IIS Temporary Compressed Files IIS 7。

    对于 IIS 7) ,IIS_WPG (IIS_IURS必须对此文件夹具有完全控制权限。 进程监视器是排查此类权限问题的绝佳工具。

    进程监视器

  3. 检查是否在Metabase.xml中启用了压缩: 未在正确的位置的元数据库中打开压缩。 压缩配置有三个元数据库位置:

    w3svc/filters/compression/parameters
    
    w3svc/filters/compression/gzip
    
    w3svc/filters/compression/deflate
    

    在 /parameters 位置配置是 *必需*。 然后,需要在 /gzip *或* /deflate、*或两者中配置。 这意味着在 /gzip 处进行配置将不起作用,而仅 /deflate 将不起作用,而仅 /parameters 将不起作用。 但是,在 /parameters 和 /gzip 上配置将启用 Gzip 压缩方案。 配置 /parameters 和 /deflate 将启用 Deflate 压缩方案。 最后,配置所有三者都将启用 GZip 压缩和 Deflate 压缩。

  4. 检查 IIS 6 的元数据库权限: 默认情况下,IIS_WPG具有对 /LM/W3SVC/Filters 的读取、不安全读取、枚举密钥和写入权限。

    如果由于意外更改或安全强化而删除了权限,IIS 将无法初始化压缩。

    使用metaacl.vbs验证和修改 IIS 6 元数据库 ACL。 (https://www.microsoft.com/download/en/details.aspx?displaylang=en&id=4899)

    默认元数据库 ACL

    如果应用程序池标识 (或IIS_WPG组通常) 没有对元数据库密钥 W3SVC/Filters 的读取和写入访问权限,则会在 Windows (ETW) 跟踪的企业跟踪中记录COMPRESSION_DISABLED失败条件。

    ETW 跟踪:

    IISCompression: STATIC_COMPRESSION_NOT_SUCCESS - IIS has been unsuccessful doing static compression
    Reason: COMPRESSION_DISABLED
    
  5. 检查是否在Metabase.xml中关闭动态或静态压缩: 在三个配置位置 (/parameters、/gzip 和 /deflate) ,可以选择启用静态和/或动态压缩。 若要压缩 txt 和 html 等静态文件,需要将 HcDoStaticCompression 键设置为 1 (或 TRUE) 。 若要为 asp、aspx、asmx、exe) 等内容启用动态压缩 (,需要将 HcDoDynamicCompression 设置为 1 (或 TRUE) 。

    例如,若要使用 adsutil.vbs 在 /parameters 节点上设置动态压缩,请运行以下命令:

    cscript.exe adsutil.vbs SET w3svc/filters/compression/parameters/HcDoDynamicCompression TRUE
    

    该命令的输出如下所示:

    HcDoDynamicCompression          : (BOOLEAN) True
    

    在 IIS7 中:

    <system.webServer>
        <urlCompression doStaticCompression="true" doDynamicCompression="true" />
    </system.webServer>
    
  6. 检查要压缩的文件类型是否列在 /gzip 和 /deflate 节点的相应文件扩展名部分中: 使用 HcDoDynamicCompression 和/或 HcDoStaticCompression 键启用压缩后,必须确保告知 IIS 实际压缩哪些文件类型。 默认情况下,我们将压缩 htm、html 和 txt 进行静态压缩,以及用于动态压缩的 asp、dll 和 exe。 如果需要压缩不同的文件类型(例如 aspx),则需要将其添加到 /gzip 和/or /deflate 节点中的相应文件扩展名部分,具体取决于所使用的压缩类型。 对于静态文件压缩 ((如 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文件中, (元数据库直接编辑) 是个坏主意。始终手动键入它!

  7. 检查是否在主级别设置压缩,但是通过子级别设置重写的: 压缩将在 w3svc/filters/compression 级别启用,但如果有可能通过网站/应用程序级别的设置来替代压缩。

    例如: 如果 HcDoDynamicCompression 在 w3svc/filters/compression 级别设置为 TRUE,并且对于默认网站将 DoDynamicCompression 设置为 FALSE,则不会对对默认网站请求的响应进行动态压缩。

  8. 检查防病毒程序是否已扫描存储压缩文件的目录:

    在运行 Internet Information Services 的服务器上启用压缩 (IIS) ,并从 IIS 压缩目录提供 HTTP 请求时,可能会返回 0 字节文件,而不是预期文件。

    注意

    如果启用了 HTTP 静态压缩,则只能看到这些症状。

    这是因为 IIS 服务器上运行的防病毒软件正在扫描 IIS 压缩目录。

    因此,需要从防病毒软件的扫描列表中排除 IIS 压缩目录。

    请参阅: https://support.microsoft.com/?id=817442

  9. 检查所请求的 URL 是否包含斜杠,作为传递给执行 DLL 文件的参数的一部分。

  10. ISAPI 筛选器修改请求/响应标头:

    ISAPI 正在执行发送操作,并且未将完整的 HTTP 标头集与实体一起发送到 HTTP_COMPRESSION::D oDynamicCompression。 由于 DoDynamicCompression 不会从 ISAPI 接收它应接收的所有数据,因此无法压缩响应。 第三方和非 Microsoft ISAPIs 通过将标头置于用于实体正文的函数中或针对 HTTP 标头的函数中的实体正文,或者不提供任何标头来执行此操作。 发生这种情况时,ISAPI 筛选器SF_NOTIFY_SEND_RESPONSE或 AddResponseHeaders 或动态压缩等操作将失败。 ISAPI 需要分别将标头和实体放在正确的位置。

  11. 响应状态代码不是 200。 在 IIS 6/7 中,只有具有 HTTP 200 状态的响应才会压缩。

    是的,这两个 IIS6 & IIS 7.x 中都是如此,不会压缩包含 200 以外的状态代码的响应。 我们必须编写 HTTPModule 才能实现相同的目的。

  12. 如果请求包含 Via: 标头: Via 标头指示请求通过代理传入 IIS。 许多代理不会正确处理压缩标头,并且当客户端不应处理压缩数据时提供给客户端,因此默认情况下,当请求具有 Via 标头时,我们不允许压缩响应。 可以通过将 HcNoCompressionForProxies 元数据库密钥设置为 True 来替代此功能。

  13. 请求适用于静态页面,响应包含文档页脚。 文档页脚将导致静态压缩失败。

  14. 静态压缩不起作用: 如果在 IIS 中根级别安装了通配符应用程序映射,则可能会发生此情况。 例如, 我们在服务器上具有.html或.txt扩展的应用程序映射) ,这会使 IIS 将请求视为动态请求 .txt而不是静态请求,并且由于.txt不是动态压缩列表中的扩展,因此不会进行压缩。

  15. IIS 压缩和“Accept-Encoding: identity”:

    根据 RFC2616:

    “如果请求中存在Accept-Encoding字段,并且服务器无法根据Accept-Encoding标头发送可接受的响应,则服务器应发送错误响应,并显示 406 (”不可接受) 状态代码”。 如果请求中不存在Accept-Encoding字段,服务器 MAY 假定客户端将接受任何内容编码。 在这种情况下,如果“identity”是可用内容编码之一,则服务器应使用“标识”内容编码,除非它具有其他信息,即其他内容编码对客户端有意义。

  16. 使用 ETW 跟踪排查 IIS 压缩问题

    Windows (ETW) 事件跟踪是 Windows 操作系统的一项功能,可用于排查 HTTP 请求的问题。

    下面是排查 IIS 压缩问题的步骤。

    • 创建名为IISProviders.txt的文本文件,并将关注内容放入文件中。IIS:WWW Server“是提供程序名称,0xFFFFFFFE表示所有事件的跟踪,5 表示详细级别。

      “IIS: WWW Server” 0xFFFFFFFE 5 有关详细信息,请参阅 IIS 提供程序: https://technet.microsoft.com/library/cc758221(v=ws.10).aspx

    • 打开命令窗口,然后运行以下命令:

      logman start trace compressionTrace -pf IISProviders.txt -ets
      
    • 再现此问题。

    • 运行以下命令以停止跟踪。

      Logman stop trace compressionTrace -ets
      
    • 将跟踪转换为文本文件。

      跟踪报表将二进制跟踪数据转换为文本,并在执行 tracerpt 命令的目录中生成两个文件:

      tracerpt compressionTrace.etl
      

      Summary.txt 包含有关跟踪会话的一般详细信息,包括使用哪些提供程序。

      DumpFile.csv 包含文本格式的实际跟踪数据。

    • 读取跟踪文件以查找有用的信息。 打开dumpfiles.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 没有压缩方案匹配。 有关压缩错误的详细列表,请参阅附录中的表。

  17. 使用 FREB 跟踪排查 IIS 压缩问题

    与 ETW 跟踪相比,IIS 7 FREB 跟踪更容易。 有关详细信息步骤,请参阅本文。

    https://www.iis.net/learn/troubleshoot/using-failed-request-tracing/troubleshooting-failed-requests-using-tracing-in-iis

    下面是使用 IIS 7 FREB 跟踪排查压缩问题的示例。

    使用错误消息跟踪压缩问题的屏幕截图。

    有关压缩错误的详细列表,请参阅附录中的表。

    附录:

    表 1:原因适用于 IIS 6 和 IIS 7

    原因 说明
    NO_ACCEPT_ENCODING 客户端未发送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 响应中已存在内容编码

    表 2:原因仅适用于 IIS 7。

    原因 说明
    FOOTER_ENABLED 为静态文件启用文档页脚
    NOT_FREQUENTLY_HIT URL 请求的频率不够大,无法证明压缩是正当的
    FAIL_TO_COMPRESS 无法创建压缩副本

其他资源