WCF服务中的缓冲区大小

问题描述:

我们有一个WCF服务,它执行某些存储过程并将结果返回给silverlight客户端。一些存储过程返回高达80K行。WCF服务中的缓冲区大小

下面给出的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,服务抛出一个错误或者超时或NotFound。你为什么认为这会发生?我该如何解决?

+1

你确定你想从一个调用返回80K行?也许重构和使用“分页”结果会更合适? – Jon 2011-03-17 09:57:50

+0

我知道这听起来很荒谬,但我的用户很想将它显示在网格上(当然,我们用分页显示它们)。大多数第三方网格像Telerik支持它虽然 – Kev 2011-03-17 09:57:59

+0

你可以试着在multipe calls中获取这些数据DownloadPage(1)... n你将得到所有的数据,但是以smaler块 – kalvis 2011-03-17 10:00:58

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

+0

我同意这个答案。展望未来,显示结果的最佳方式是在用户寻找下一页时获取更少量的数据。但目前,我需要一个快速解决方案,因为这个问题发生在生产系统中。 – Kev 2011-03-17 10:32:49

+1

@Kev你*可能*很幸运,并找到一种方法来做到这一点,但并非所有事情都可以通过快速解决。它*可能会更快地停止花时间寻找快速修复,并解决根本问题。 – 2011-03-17 10:43:36

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

readerQuotas

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

这应该工作。如果需要增加缓冲区大小。

我们已成功地在客户端和WCF服务之间使用GZIP压缩来增加我们可以撤回的行数。还应该适合您的需求。

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