2011-11-22 27 views
20

我在WCF中创建了一个Web服务,该服务返回每行有10个数据的54000多个数据行。我已经使用wsHttpBinding进行通信。该服务在数据较少(即2000行)的情况下工作良好,但当尝试发送50000行(〜2MB)的大型记录集时,该服务会弹出。异常消息是这样的在WCF服务中传输大量数据

接收到对http://localhost:9002/MyService.svc的HTTP响应时发生错误。这可能是由于服务端点绑定不使用HTTP协议。这也可能是由于HTTP请求上下文被服务器中止(可能是由于服务关闭)。查看服务器日志获取更多详细信

请不要告诉我在客户端使用分页 - 我知道它会解决问题。但是我需要客户端的整个数据块。在服务器

我的服务配置是

<system.serviceModel> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="MyWsHttpBinding" /> 
    </wsHttpBinding> 
    </bindings> 
    <services> 
    <service name="AdminService"> 
     <endpoint address="AdminSrv" 
       binding="wsHttpBinding" 
       contract="IAdminService"/> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     <host> 
     <baseAddresses> 
      <add baseAddress="/Bus/IRfotoWCF" /> 
     </baseAddresses> 
     </host> 
    </service> 
    </services> 
    <behaviors> 
    <serviceBehaviors> 
     <behavior> 
     <!-- To avoid disclosing metadata information, 
        set the value below to false and remove the metadata endpoint above before deployment --> 
     <serviceMetadata httpGetEnabled="True"/> 
     <!-- To receive exception details in faults for debugging purposes, 
        set the value below to true. Set to false before deployment 
        to avoid disclosing exception information --> 
     <serviceDebug includeExceptionDetailInFaults="True" /> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"></serviceHostingEnvironment> 
</system.serviceModel> 

我的客户端配置是

<system.serviceModel> 
    <bindings> 
    <basicHttpBinding> 
     <binding name="BasicHttpBinding_IAdminService" closeTimeout="00:01:00" 
       openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 
       allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
       messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
       useDefaultWebProxy="true"> 
     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
         maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
     <security mode="None"> 
      <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> 
      <message clientCredentialType="UserName" algorithmSuite="Default" /> 
     </security> 
     </binding> 
    </basicHttpBinding> 
    </bindings> 
    <client> 
    <endpoint address="http://localhost/TestService/AdminService.svc" 
       binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IAdminService" 
       contract="IAdminService" name="BasicHttpBinding_IAdminService" /> 
    </client> 
</system.serviceModel> 

会有人帮助我无论是在客户端和服务器端的配置excact。即使我需要更改绑定从wsHttpBindingnetTcpBinding - 我没有这样做的问题。提前致谢。

回答

33

经过大量调查,我得到了解决方案。其实很多事情都需要改变。

以下更改需要在服务器端中完成。

首先我只好一个的maxRequestLength的httpRuntime元素设置为一个较大的值来运行较长时间的请求。

<system.web>  
<httpRuntime maxRequestLength="102400" /> 
</system.web> 

我介绍NetTcpBinding的 binnding与maxBufferSize, maxBufferPoolSize, maxReceivedMessageSize2147483647一个较大的值自定义更改。

<binding name="myNetTcpBinding" 
maxBufferPoolSize="2147483647" 
maxBufferSize="524288" 
maxReceivedMessageSize="2147483647"> 

同时在serviceBehaviorsendpointBehaviors像波纹管的加入maxItemsInObjectGraph(不要忘了提到在serviceendpoint节点的行为名称)

<behaviors> 
     <serviceBehaviors>   
     <behavior name="myNetTcpBehaviour"> 
      <serviceMetadata httpGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
     </behavior> 
     </serviceBehaviors> 
     <endpointBehaviors> 
     <behavior name="myNetTcpEndPointBehaviour"> 
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 

最后我的服务器配置如下像这样

<system.web>  
    <httpRuntime maxRequestLength="102400" /> 
</system.web> 


    <system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="MyWsHttpBinding" /> 
     </wsHttpBinding> 
     <netTcpBinding> 
     <binding name="myNetTcpBinding" 
       closeTimeout="00:01:00" 
       openTimeout="00:01:00" 
       receiveTimeout="00:10:00" 
       sendTimeout="00:01:00" 
       transactionFlow="false" 
       transferMode="Buffered" 
       transactionProtocol="OleTransactions" 
       hostNameComparisonMode="StrongWildcard" 
       listenBacklog="10" 
       maxBufferPoolSize="2147483647" 
       maxBufferSize="524288" 
       maxConnections="10" 
       maxReceivedMessageSize="2147483647"> 
      <readerQuotas maxDepth="32" 
         maxStringContentLength="8192" 
         maxArrayLength="16384" 
         maxBytesPerRead="4096" 
         maxNameTableCharCount="16384" /> 
      <reliableSession ordered="true" 
          inactivityTimeout="00:10:00" 
          enabled="false" /> 
      <security mode="Transport"> 
      <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <services> 
     <service name="AdminService" behaviorConfiguration="myNetTcpBehaviour"> 
     <endpoint address="AdminSrv" 
        binding="netTcpBinding" 
        bindingConfiguration="myNetTcpBinding" 
        contract="IAdminService" 
        behaviorConfiguration="myNetTcpEndPointBehaviour"/> 

     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="/Bus/IRfotoWCF" /> 
      </baseAddresses> 
     </host> 
     </service> 
    <behaviors> 
     <serviceBehaviors>   
     <behavior name="myNetTcpBehaviour"> 
      <serviceMetadata httpGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
     </behavior> 
     </serviceBehaviors> 
     <endpointBehaviors> 
     <behavior name="myNetTcpEndPointBehaviour"> 
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"></serviceHostingEnvironment> 
    </system.serviceModel> 

现在在客户端 configuratioin您需要更改maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"

还需要在终结点行为配置中添加maxItemsInObjectGraph="2147483647"仍有很多 -

 <endpointBehaviors> 
      <behavior name="myEndPointBehavior"> 
       <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
      </behavior> 
     </endpointBehaviors> 

现在我可以内5.30分钟其中查询执行,持续10秒,因此传输时间是5.20分钟发送行。

欢迎评论和任何改进建议。

+0

我不明白。这是一个非常好的解决方案,当一个服务在5.20分钟内等待另一个服务时。我认为这是关于建筑的一个大问题,但我找不到解决方案。 – Vladislav

+0

我继续用传输大数据测试速度。使用“Chunks”方法,我可以发送300 000(!)行,在4.34分钟内将其保存到数据库,而不会对我的服务配置做任何更改。我只是将我的数据分为50行的块。 – Vladislav

+0

您应该使用Datacontract Serializer代替XML。这是迄今为止reference.cs中的手动替换作业。 – NickD

1

如果您查看绑定详细信息,它们不会完全匹配服务器和客户端的匹配。 maxBufferSize, maxBufferPoolSize, maxReceivedMessageSize的属性也将在服务器端定义。然后你需要根据你正在查看的大小来设置值。

+0

我已经尝试这些maxBufferSize,maxBufferPoolSize,maxReceivedMessageSize与值2147483647都在服务器端和客户端。仍然是例外。 –

+0

我无法在您的帖子中看到配置文件中的设置。你确定绑定配置设置正确吗? – Kangkan

+0

Yap,我在服务器和客户端的本地配置绑定配置中。但是现在我已经解决了这个问题 - 请看答案。无论如何,谢谢你随时评论答案。 –

-3

使用用户定义的表类型(如果您使用的是SQL),而不是使用for循环遍历WCF处理庞大的数据。它会将时间从6分钟缩短到15-20秒。

+0

只是...... ......? – Gareth