【问题标题】:Buffer size in WCF serviceWCF 服务中的缓冲区大小
【发布时间】:2011-03-17 09:52:24
【问题描述】:

我们有一个 WCF 服务,它执行某些存储过程并将结果返回给 silverlight 客户端。一些存储过程最多返回 80K 行。

以下是 web.config 中服务的设置

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <behaviors>
       <serviceBehaviors>
           <behavior name="MyService.MyServiceBehavior">
               <serviceMetadata httpGetEnabled="true"/>
               <serviceDebug includeExceptionDetailInFaults="true"/>
               <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
           </behavior>
       </serviceBehaviors>
    </behaviors>
    <bindings>
       <basicHttpBinding>
           <binding name="BasicHttpBinding_MyService" 
                maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" 
                receiveTimeout="00:40:00" openTimeout="00:40:00" 
                closeTimeout="00:40:00" sendTimeout="00:40:00">
                <readerQuotas maxDepth="2147483647" 
                    maxStringContentLength="2147483647" maxArrayLength="2147483647" 
                    maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
                <security mode="None"/>
           </binding>
        </basicHttpBinding>
        <customBinding>
           <binding name="MyService.MyService.customBinding0">
              <binaryMessageEncoding/>
              <httpTransport/>
            </binding>
        </customBinding>
     </bindings>
     <services>
          <service behaviorConfiguration="MyService.MyServiceBehavior" 
                   name="MyService.MyService">
              <endpoint name="BasicHttpBinding_MyService" 
                  address="" 
                  binding="basicHttpBinding" 
                  bindingConfiguration="BasicHttpBinding_MyService" 
                  contract="MyService.IMyService"/>
           </service>
     </services>
</system.serviceModel>

这是给客户的

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 
    <behaviors>
       <serviceBehaviors>
           <behavior name="MyService_Behavior">
              <serviceDebug includeExceptionDetailInFaults="true"/>
              <serviceMetadata httpGetEnabled="true"/>
           </behavior>
       </serviceBehaviors>
       <endpointBehaviors>
          <behavior name="r1">
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          </behavior>
       </endpointBehaviors>
    </behaviors>
    <bindings>
       <basicHttpBinding>
            <binding name="BasicHttpBinding_MyService" 
                closeTimeout="00:03:00" openTimeout="00:03:00" 
                receiveTimeout="00:10:00" sendTimeout="00:03:00" 
                allowCookies="false" bypassProxyOnLocal="false" 
                hostNameComparisonMode="StrongWildcard" 
                maxBufferSize="2147483647" maxBufferPoolSize="2147483647" 
                maxReceivedMessageSize="2147483647" 
                messageEncoding="Text" textEncoding="utf-8" 
                transferMode="Buffered" useDefaultWebProxy="true">
               <security mode="None"/>
             </binding>
        </basicHttpBinding>
     </bindings>
     <client>
        <endpoint name="BasicHttpBinding_MyService"
            address="http://localhost:8080/MyService/MyService.svc" 
            behaviorConfiguration="r1"
            binding="basicHttpBinding" 
            bindingConfiguration="BasicHttpBinding_MyService" 
            contract="MyService.IMyService"  />
    </client>
</system.serviceModel>

只要记录数超过 20K,服务就会抛出 TimeOut 或 NotFound 错误。您认为为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 您确定要从一次调用中返回 80K 行吗?也许重构和使用“分页”结果会更合适?
  • 我知道这听起来很荒谬,但我的用户非常想将它显示在网格上(当然,我们让它们显示为分页)。不过,像 Telerik 这样的大多数第三方网格都支持它
  • 您可以尝试在多次调用 DownloadPage(1) 中获取该数据 ... n 您将获得所有数据,但以更小的块形式

标签: c# silverlight wcf


【解决方案1】:

这听起来像是纯粹的数据过载。如 cmets 中所述,分页是一种实用的解决方案。如果有充分的理由需要 80k,您可以尝试使用不同的机制来序列化数据。例如,protobuf 数据通常比 xml 小 很多,因此您可以尝试在线上使用它。但是,由于这是 Silverlight,我不能(当前)自动交换它 - 您需要返回 byte[]Stream 并在服务器/客户端显式处理序列化/反序列化。这应该会大大降低带宽要求(如果您可以将 Silverlight 配置为使用 MTOM,则更甚——我最近没有检查过,但一些早期版本不支持此功能)。

【讨论】:

  • 我同意这个答案。展望未来,显示结果的最佳方式是在用户寻找下一页时获取更少量的数据。但目前,我需要快速解决此问题,因为此问题发生在生产系统中。
  • @Kev 您可能会走运并找到一种方法来做到这一点,但并非所有事情都可以通过快速修复来解决。 可能停止花时间寻找快速解决方案,而只解决根本问题会更快。
【解决方案2】:

当您的 proc 返回 80K 时,您还必须在客户端添加缓冲区大小。

readerQuotas

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>

这应该可行。如果需要,请增加缓冲区大小。

【讨论】:

    【解决方案3】:

    我们已成功在客户端和 WCF 服务之间使用 GZIP 压缩来增加我们可以拉回的行数。也应该满足您的需求。

    我们使用 MS 库来实现它: http://msdn.microsoft.com/en-us/library/ms751458.aspx

    【讨论】:

      猜你喜欢
      • 2021-02-25
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多