【问题标题】:GZip compression with WCF hosted on IIS7使用 IIS7 上托管的 WCF 进行 GZip 压缩
【发布时间】:2011-02-12 09:09:03
【问题描述】:

就我而言,每个人都在编辑 2 中解决了这个问题。虽然这只是问题的 IIS 方面的部分解决方案,但它正是我所寻找的。​​p>


因此,我将把我的查询添加到有关该主题的大量问题中。

我正在尝试对来自 WCF 服务的大型肥皂响应启用 GZip 压缩。到目前为止,我已经按照here 和其他各种地方的说明在 IIS 上启用动态压缩。这是我在 applicationHost.config 中的 dynamicTypes 部分:

<dynamicTypes>
    <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="application/xop+xml" enabled="true" />
    <add mimeType="application/soap+xml" enabled="true" />
    <add mimeType="*/*" enabled="false" />
</dynamicTypes>

还有:

<urlCompression doDynamicCompression="true" doStaticCompression="true" />

虽然我不太清楚为什么需要这样做。

为了以防万一,在其中添加了一些额外的 mime 类型。 我已经实现了 IClientMessageInspector 来添加 Accept-Encoding: gzip, deflate 到我客户的 HttpRequests。以下是取自 fiddler 的请求标头示例:

POST http://[omitted]/TestMtomService/TextService.svc HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Accept-Encoding: gzip, deflate
Host: [omitted]
Content-Length: 542
Expect: 100-continue

现在,这行不通。无论消息大小如何(尝试最大为 1.5Mb),都不会发生压缩。我看过this post,但没有遇到他描述的异常,所以我没有尝试过他提出的CodeProject实现。此外,我还看到了很多其他的实现,它们应该可以让它工作,但无法理解它们(例如,msdn's GZip encoder)。为什么我需要实现编码器或代码项目解决方案? IIS 不应该负责压缩吗?

那么我还需要做什么才能让它发挥作用?

乔尼

编辑: 我认为 WCF 绑定可能值得发布,但我不确定它们是否相关(这些来自客户端):

<system.serviceModel>
<bindings>
    <wsHttpBinding>
    <binding name="WsTextBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
      receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
      transactionFlow="false" hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="5000000" maxReceivedMessageSize="5000000"
      messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
      allowCookies="false">
      <readerQuotas maxDepth="32" maxStringContentLength="5000000"
        maxArrayLength="5000000" maxBytesPerRead="5000000" maxNameTableCharCount="5000000" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00"
        enabled="false" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
        <message clientCredentialType="None" negotiateServiceCredential="false"
          algorithmSuite="Default" establishSecurityContext="false" />
      </security>
<client>
  <endpoint address="http://[omitted]/TestMtomService/TextService.svc"
   binding="wsHttpBinding" bindingConfiguration="WsTextBinding" behaviorConfiguration="GzipCompressionBehavior"
   contract="TestMtomModel.ICustomerService" name="WsTextEndpoint">
  </endpoint>
</client>
<behaviors>
  <endpointBehaviors>
    <behavior name="GzipCompressionBehavior">
      <gzipCompression />
    </behavior>
  </endpointBehaviors>
</behaviors>
<extensions>
  <behaviorExtensions>
    <add name="gzipCompression"
         type="TestMtomModel.Behavior.GzipCompressionBehaviorExtensionElement, TestMtomModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </behaviorExtensions>
</extensions>
    </binding>
  </wsHttpBinding>
</bindings>

编辑 2: 好吧,对于处于这种神秘情况的其他人,我有一个部分解决方案。即,我已经让 IIS7 至少压缩了来自服务的肥皂消息(尽管我现在在客户端上遇到了一个异常,但是已经发布了几个解决方案)。 问题是我的服务器上没有安装 DynamicCompressionModule。实际上,对我来说,“安装”它意味着只需将这一行添加到 applicationHost.config 的部分:

<add name="DynamicCompressionModule" image="%windir%\System32\inetsrv\compdyn.dll" />

(假设 dll 存在于该目录中,在我的情况下它确实存在。) 然后通过 IIS7 的 Modules 部分为网站或服务器添加模块。

【问题讨论】:

  • 可能是一个愚蠢的问题,但它欺骗了我一段时间 - 你怎么知道压缩没有发生?如果是因为您没有在 Fiddler 中看到它,请注意 Fiddler 会自动解压缩,除非您告诉它不要这样做。

标签: wcf iis-7 http-compression


【解决方案1】:

尝试添加 'application/soap+xml; charset=utf-8' 作为 applicationHost 中的动态类型。添加这个字符集部分帮助我为来自我的 http 处理程序的一些 JSON 响应启用压缩。

【讨论】:

  • +1 - 这就是答案 - 我必须这样做才能在不使用任何其他组件的情况下进行压缩。也就是说,假设打开并安装了动态压缩模块:)
  • 您可能需要多次启用相同的 mime 类型,因为 Microsoft 倾向于进行字符串比较而不是内容比较。 (即application/soap+xml;charset=utf-8application/soap+xml;charset=ISO-8895-1application/soap+xml; charset=ISO-8895-1
  • 在 IIS7 中为 WCF 数据馈送、OData 和其他自定义服务启用动态压缩(gzip、deflate)---hanselman.com/blog/…
【解决方案2】:

这与@marko 的答案基本相同——有详细的步骤。每次我重新审视它时,这都是一个令人沮丧的话题,所以我想概述一下我需要做的所有事情才能让它发挥作用。

  • 首先,您需要在 IIS7 上使用 .NET 4。这是因为直到 .NET 4,WCF 才能够自动解压缩 gzip 流。 'Whats new in WCF 4' 中描述了这方面的详细信息(反馈中的一些有用的 cmets)。

    我们做了 使用 HTTP 时更容易 允许客户端自动 使用 gzip 或 deflate 协商 压缩流,然后 自动解压。

  • 其次,确保您已在 IIS 中启用动态压缩模块。您可能需要转到“程序和功能”来安装它。确保您已为相关 Web 应用程序启用它 - 因为它不是全局设置。

  • 现在 WPF 使用 MIME 类型 application/soap+xml; charset=utf-8 进行 HTTP 传输(至少使用 wsHttpBinding 是这样)。 默认情况下,这不是动态类型,因此需要将其添加到 applicationHost.config 文件中。

    只需在服务器上编辑此文件:C:\Windows\System32\Inetsrv\Config\applicationHost.config

    &lt;dynamicTypes&gt; 节点中添加以下行(在 / 行之前):

    <add mimeType="application/soap+xml; charset=utf-8" enabled="true" />
    

    More on the applicationHost.config file

  • 重启 IIS

您现在应该有压缩数据 - 可以在 Fiddler. 中验证

【讨论】:

  • 这篇文章是精华。万分感谢! (令人惊讶的是正确的帖子如何让您到达那里......而其他人只是混淆!)
  • 抱歉这个愚蠢的问题,但为什么不能在应用程序的 web.config 中设置这个 mimeType?这个我试过了,不行。但为什么?它不适合我在每台服务器上编辑 applicationhost.config,我的应用程序托管在哪里。
【解决方案3】:

我也一直在努力解决这个问题,并且无法让它与我的 .svc 一起使用,即使它在同一个应用程序中处理 .aspx 文件也很好。事实证明,它只适用于 basicHttpBinding 而不是 wsHttpBinding 或二进制编码的 customBinding。这对我来说很好,因为压缩因子超过了二进制编码器的好处(它将消息大小减少了很多,但不是压缩给出的 10 倍)。

【讨论】:

  • 请参阅我的回答,了解为什么它适用于 basicHttpBinding 而不适用于 wsHttpBinding。有办法!
【解决方案4】:

最好的办法是评估您遇到问题的特定 mime 类型(例如 Fiddler),并确保将其包含在 applicationHost.config 中。如果压缩已正确安装和配置,失败的请求跟踪将让您知道未使用“NO_MATCHING_CONTENT_TYPE”处置执行压缩。

【讨论】:

  • 感谢大家的回答。但是,IIS 方面的问题已经解决了。请阅读原帖中的 EDIT 2。如果可以的话,我会将此问题标记为答案,即使这只是问题的部分解决方案,但我不能。
【解决方案5】:

mime 类型最有可能是Application/octet-stream

【讨论】:

    【解决方案6】:

    仅适用于可能展望未来的其他人。我们升级到 Windows 2012 服务器和 IIS 8。适用于 IIS 7 的旧配置压缩 mimetype 不适用于 IIS 8。

    所以,我在这里尝试了几个建议,但都没有奏效。我最终只是将它添加到 httpcompression 动态类型:multipart/* 然后 gzip 压缩再次工作。

    希望这对其他人有所帮助。

    【讨论】:

      【解决方案7】:

      很多人都在为 WCF 服务启用 IIS 级别压缩而苦苦挣扎。主要是人们在 wsHttpBinding 上苦苦挣扎,如果在 IIS 中启用了动态压缩,basicHttpBinding 就会开箱即用地进行压缩。我不打算讨论如何启用动态压缩,因为它在许多不同的帖子中都有介绍,只需搜索“iis compression application/soap+xml”。如前所述,如果您已正确配置所有内容,您应该能够在响应标头中看到使用 Content-Encoding: gzip 压缩的 WCF 响应。我建议使用 Fiddler 来跟踪您的请求/响应。这是我(任何其他人)使用 basicHttpBinding 的经验。那么问题就变成了为什么它不能与 wsHttpBinding 一起使用?毫无疑问,您已经读过这是因为这两个绑定之间的 Content-Type 不同。 basicHttpBinding 使用 Content-Type: text/xml; charset=utf-8 其中 wsHttpBinding 使用 Content-Type: application/soap+xml;字符集=utf-8。前者包含在 dynamicTypes 下的默认 IIS applicationHost.config 设置中。后者不是。您可能读到需要添加这个额外的 mimeType 并重新启动 IIS 来解决这个问题。这对某些人有效,但对许多人无效。有些人宣称它与 wsHttpBinding 根本不兼容。这是问题所在。可能有 两个 applicationHost.config 文件:

      C:\Windows\System32\inetsrv\config
      C:\Windows\SysWOW64\inetsrv\Config
      

      System32 是 64 位的,是您安装 IIS 时使用的。这也是您为添加额外的 mimeType 而修改的那个,或者您认为的!

      cannot manually edit applicationhost.config - MUST READ

      事实证明,如果您使用 Notepad++ 等 32 位应用程序,您最终修改的是 SysWOW64 文件夹中的文件。这对你来说是完全透明的。如果您使用常规记事本应用程序,您会注意到您添加的 mimeType 实际上不在位于 System32 文件夹中的文件中,它被神奇地添加到 SysWOW64 文件夹中,即使您从未真正浏览过它文件夹开始。希望这可以为您节省数小时的悲伤。

      【讨论】:

        【解决方案8】:

        如果有人在以 WebApp 形式在 Azure 中托管时偶然发现此问题,您可以使用名为“IIS 管理器”的扩展名配置 applicationHost.config,并使用“扩展”下的 azure 门户。有关扩展程序本身的更多信息https://github.com/shibayan/IISManager

        【讨论】:

          猜你喜欢
          • 2010-10-21
          • 2011-02-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-22
          • 2012-09-19
          • 2011-11-28
          相关资源
          最近更新 更多