2011-11-22 15 views
20

WCFで、各行に10個のデータを含む54000個以上のデータ行を返すWebサービスを作成しました。私は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> 

として私のクライアント構成である誰かが両方のクライアント側とサーバー側でexcact構成で私を助けるだろう

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

ようです。たとえ私がバインドを変更する必要があっても、wsHttpBindingからnetTcpBinding - 私はそれを行うことに問題はありません。前もって感謝します。

答えて

33

多くの調査の後、finnally私は解決策を得た。実際には多くのことを変更する必要があります。

サーバー側で次の変更を行う必要がありました。

まず私は長い期間のための要求を実行するために、私ののhttpRuntime要素に大きな値にmaxRequestLengthを設定する必要がありました。第二に

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

iは2147483647の値が大きいmaxBufferSize, maxBufferPoolSize, maxReceivedMessageSize上のカスタム変更をnetTcpBinding binndingを導入しました。第三は(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> 

最後に私のサーバー構成のルックスserviceBehaviorsと怒鳴るなどのendpointBehaviorsの両方でmaxItemsInObjectGraphを追加

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

このように

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

は今、あなたはmaxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"

を変更する必要がクライアント側 configuratioinにも、あなたはエンドポイントの動作設定でmaxItemsInObjectGraph="2147483647"を追加する必要があります。依然として多く -

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

今は送信時間は5.20分であるので、クエリが10秒間実行5.30分内行を送信することができます。

コメントをお寄せください。また改善の提案もあります。

+0

私は分かりません。 1つのサービスが5.20分に別のサービスを待っているときは、本当に良い解決策ですか?ここではアーキテクチャに関する大きな疑問があると思いますが、私は解決策を見つけることができません。 – Vladislav

+0

大きなデータを転送しながら速度をテストし続けます。 "Chunks"メソッドを使用すると、私は300 000(!)の行を送り、サービスの設定を変更せずに4.34分以内にデータベースに保存することができます。私はちょうど50行のチャンクのために私のデータを分けています。 – Vladislav

+0

XMLの代わりにDatacontractシリアライザを使用する必要があります。これは、これまでのところ、reference.cs内の手動置換ジョブです。 – NickD

1

バインディングの詳細を見ると、サーバー上とクライアント側では完全に一致しません。 maxBufferSize, maxBufferPoolSize, maxReceivedMessageSizeの属性は、サーバー側でも定義されます。そして、あなたはあなたが見ているサイズに応じて値を入れる必要があります。

+0

私はこれらのmaxBufferSize、maxBufferPoolSize、maxReceivedMessageSizeの値を2147483647とサーバー側とクライアント側の両方で試しました。まだ同じ例外です。 –

+0

あなたの投稿の設定ファイルの設定を見ることができませんでした。バインド設定が正しく設定されていますか? – Kangkan

+0

私はローカルとサーバ側のバインディング設定でそれらを設定しました。しかし、今私は問題を解決しました。答えを見てください。とにかくおかげで、plzは答えにコメントを自由に感じる。 –

-3

大量のデータに対してforループオーバーWCFを使用する代わりに、ユーザー定義のテーブルタイプを使用します(SQLを使用している場合)。それは6分から15-20秒に時間を短縮します。

+0

ちょっと...... ......? – Gareth