web-dev-qa-db-ja.com

WCFサービスで大量のデータを転送する

WCFで、各行に10個のデータを持つ54000個以上のデータ行を返すWebサービスを作成しました。通信にwsHttpBindingを使用しました。このサービスは少ないデータ(つまり2000行)でうまく機能しますが、50000行以上(〜2MB)の大きなレコードセットを送信しようとすると爆撃されます。例外メッセージはこのようなものです

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>

誰かがクライアント側とサーバー側の両方で正確な設定を手伝ってくれますか?バインディングをwsHttpBindingからnetTcpBindingに変更する必要がある場合でも、問題なく実行できます。前もって感謝します。

20
Rizvi Hasan

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

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

最初私はmaxRequestLengthをmyhttpRuntimeより長い期間リクエストを実行する要素。

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

Second iが導入されましたnetTcpBindingmaxBufferSize, maxBufferPoolSize, maxReceivedMessageSizeの大きな値を持つ2147483647のカスタム変更によるバインド。

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

番目maxItemsInObjectGraphserviceBehaviorsの両方に以下のようにendpointBehaviorsを追加します(serviceに動作名を記載することを忘れないでくださいおよび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>

最終的に私のサーバー構成は次のようになります

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

client-side configuratioinでは、maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"を変更する必要があります

およびまた、エンドポイントの動作設定にmaxItemsInObjectGraph="2147483647"を追加する必要があります。

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

これで、 5.30 min内の行を送信できるようになりました。クエリは10秒間実行されたため、送信時間は5.20分です-still a lot

コメントや改善のための提案をお気軽に。

33
Rizvi Hasan

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

1
Kangkan