2

あるアプリケーションからメッセージを受信し、接続されている他のクライアント アプリケーションに通知を送信する WCF サービスがあります。

最初のテスト シナリオでは、1 つのクライアント アプリケーションが毎秒大量のメッセージをサービスに送信し、別の 2 つのアプリケーションがこれらのメッセージをサービスから受信しています。このテストでは、私のサービスは完璧に機能します。

ただし、メッセージを送信する別のクライアント アプリケーション (サービスにメッセージを送信する 2 つのアプリケーション) を追加すると、アプリケーションがクラッシュし、タイムアウト例外がスローされます (ほとんどの場合、SendTimeOut)。

2 回目のテストでは、リクエスト間で Thread.Sleep() を使用しているため、1 回目のテストよりも 1 秒あたりのメッセージ数が少なくなっているため、リクエストの数よりも多くのアプリケーションがリクエストを送信していることが問題だと思いますが、わかりません。

なぜこれらの問題が発生するのか知っていますか?

私のサービスとクライアント アプリケーションは次のようにコーディングされています。

サービス契約:

[ServiceContract(CallbackContract = typeof(ICacheCommunicatorServiceCallback), SessionMode = SessionMode.Required)]
public interface ICacheCommunicatorService
{
    [OperationContract(IsInitiating = true, IsOneWay = true)]
    void Connect(string appName, string machineName);

    [OperationContract(IsTerminating = true, IsOneWay = true)]
    void DisconnectClient(ICacheCommunicatorServiceCallback callback);

    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginSendNotification(Notification notification, AsyncCallback callback, object state);
    void EndSendNotification(IAsyncResult result);
}

メソッド コードのリクエスト:

public IAsyncResult BeginSendNotification(Notification notification, AsyncCallback callback, object state)
    {
        try
        {
            ICacheCommunicatorServiceCallback current = CurrentCallback;

            ClientInfo sender = clients[current];

            foreach (ICacheCommunicatorServiceCallback client in clients.Keys)
            {                   
                if (client != current)
                {                       
                    if (((ICommunicationObject)client).State == CommunicationState.Opened)
                    {
                        client.ReceiveNotification(notification);
                    }
                    else
                    {
                        DisconnectClient(client);
                    }
                }
            }
        }
        catch (Exception e)
        {
            Log(e);
        }
        return new CompletedAsyncResult();
    }

    public void EndSendNotification(IAsyncResult asyncResult) { }

サービス構成:

 <system.serviceModel>
<services>
  <service behaviorConfiguration="DefaultBehavior" name="CacheCommunicator.CacheCommunicatorService">
    <endpoint address="tcp" binding="netTcpBinding" bindingConfiguration="tcpBindingConfiguration"
      name="TcpEndpoint" contract="CacheCommunicator.ICacheCommunicatorService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" name="MexEndpoint" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8733/CacheCommunicator/" />
        <add baseAddress="http://localhost:8732/CacheCommunicator/" />
      </baseAddresses>
    </host>
  </service>
</services>
<bindings>
  <netTcpBinding>
    <binding name="tcpBindingConfiguration"
             closeTimeout="00:00:05"
             maxBufferSize="1048576"
             maxBufferPoolSize="1048576"
             maxConnections="10"
             maxReceivedMessageSize="1048576"
             openTimeout="00:00:05"
             receiveTimeout="01:00:00"
             sendTimeout="01:00:00"
             transferMode="Buffered">
      <readerQuotas maxArrayLength="1048576" maxBytesPerRead="1048576" maxStringContentLength="1048576"/>
      <reliableSession enabled="false" inactivityTimeout="01:00:00"/>
    </binding>
  </netTcpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="DefaultBehavior">
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
</behaviors>

クライアントはコールを要求します:

internal void SendNotification(Notification notification)
    {
        if (!isConnected()) this.Connect();

        Task.Factory.StartNew(() =>
        {
            proxy.SendNotification(notification);    
        }).HandleExceptions();
    }

クライアント アプリケーションの構成:

 <system.serviceModel>
<bindings>
  <netTcpBinding>
    <binding name="TcpEndpoint" 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="524288" maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
      <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"/>
        <message clientCredentialType="Windows"/>
      </security>
    </binding>
  </netTcpBinding>
</bindings>
4

2 に答える 2

0

サーバー WCF サービスのスロットリング設定を明示的に設定してみてください。

<serviceBehaviors>
   <behavior name="ServiceBehavior">
       <serviceThrottling maxConcurrentCalls="200"
                          maxConcurrentInstances ="100" 
                          maxConcurrentSessions ="100"/>
   </behavior>
</serviceBehaviors>

ところで、どの ConcurrencyMode / InstanceMode が WCF サービスに使用されますか?

おすすめの読み物:

于 2012-11-23T22:05:13.990 に答える
0

各呼び出しの後、クライアント プロキシで .Close() を呼び出していることを確認してください。プロキシの 1 つのインスタンスを介して複数の呼び出しを行うことができますが、クライアント呼び出しが完了したら、常に .Close() を実行します。

于 2013-03-14T16:55:14.847 に答える