2011-11-22 24 views
20

He creado un servicio web en WCF que devuelve más de 54000 filas de datos con 10 datos en cada fila. He usado el wsHttpBinding para la comunicación. El servicio funciona bien con menos datos (es decir, 2000 filas) pero se dispara cuando se intenta enviar un gran conjunto de registros con más de 500 filas (~ 2MB). El mensaje de excepción es asíTransferir gran cantidad de datos en el servicio WCF

Ocurrió un error al recibir la respuesta HTTP a http://localhost:9002/MyService.svc. Esto podría deberse a que el enlace del punto final del servicio no utiliza el protocolo HTTP. Esto también podría deberse a que el servidor ha cancelado un contexto de solicitud HTTP (posiblemente debido a que el servicio se ha apagado). Vea los registros del servidor para más detalles.

Por favor, no me diga que use la paginación en el lado del cliente - Sé que va a resolver el problema. Pero necesito todo el fragmento de datos en el cliente final.

Mi configuración de servicio en el servidor es tan

<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> 

Mi configuración del cliente es tan

<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> 

¿Alguien que me ayude con la configuración de excact tanto en el lado del cliente y el servidor. Incluso si necesito cambiar el enlace de wsHttpBinding a netTcpBinding - no tengo ningún problema para hacerlo. Gracias por adelantado.

Respuesta

33

Después de mucha investigación finalmente obtuve la solución. En realidad, es necesario cambiar una serie de cosas.

Los siguientes cambios se deben realizar en Server-side.

Primera tuviera que establecer un maxRequestLength a un valor mayor en mi elemento httpRuntime para ejecutar la solicitud de período más largo.

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

Segunda introduje netTcpBinding binnding con los cambios personalizados en maxBufferSize, maxBufferPoolSize, maxReceivedMessageSize con un valor grande de 2147483647.

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

Tercer añadir maxItemsInObjectGraph tanto de la serviceBehaviors y endpointBehaviors como abajo (no se olvide de mencionar los nombres de comportamiento en el nodo service y endpoint)

<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> 

Finalmente la configuración de mi servidor de miradas como este

<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> 

Ahora en el del lado del cliente configuratioin necesita cambiar la maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"

y También es necesario agregar maxItemsInObjectGraph="2147483647" en la configuración del comportamiento de punto final.

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

ahora puedo transmitir filas dentro de 5,30 min, donde la consulta ejecutado por 10 seg por lo que el tiempo de transmisión es 5,20 min - todavía mucho.

Siéntase libre de comentar y cualquier sugerencia de mejora.

+0

No entiendo. ¿Es realmente una buena solución cuando un servicio espera otro servicio durante 5,20 minutos? Creo que esta es la gran pregunta sobre la arquitectura, pero no puedo encontrar una solución. – Vladislav

+0

Continúo probando la velocidad con transferencia de datos grandes. Utilizando el método "Chunks" puedo enviar 300 000 (!) Filas, guardarlo en la base de datos dentro de 4.34min sin ningún cambio en las configuraciones de mi servicio. Solo estoy separando mis datos en trozos con 50 filas. – Vladislav

+0

Debe usar el serializador Datacontract en lugar del XML. Este es hasta ahora un trabajo de reemplazo manual dentro de los reference.cs. – NickD

1

Si mira los detalles de enlace no coinciden por completo en el servidor y el del lado del cliente. Los atributos para maxBufferSize, maxBufferPoolSize, maxReceivedMessageSize se deben definir también en el lado del servidor. Y luego debe poner los valores de acuerdo con el tamaño que está mirando.

+0

He intentado estos maxBufferSize, maxBufferPoolSize, maxReceivedMessageSize con los valores 2147483647 tanto en el servidor como en el lado del cliente. Todavía la misma excepción. –

+0

No pude ver la configuración en el archivo de configuración en su publicación. ¿Estás seguro de que la configuración de enlace está configurada correctamente? – Kangkan

+0

Yap, configuré aquellos en la configuración de enlace en mi local tanto en el servidor como en el lado del cliente. Pero ahora he resuelto el problema, mira la respuesta. Gracias de todos modos, por favor no dude en comentar la respuesta. –

-3

En lugar de usar for loop over WCF para datos voluminosos, use el tipo de tabla definido por el usuario (si está utilizando SQL). Reducirá el tiempo de 6 minutos a 15-20 segundos.

+0

¿Qué ......? – Gareth

Cuestiones relacionadas