2

我有一个 WCF 服务,它从一个应用程序接收消息并向其他连接的客户端应用程序发送通知。

在我的第一个测试场景中,一个客户端应用程序每秒向服务发送大量消息,而另外两个应用程序正在从服务接收这些消息。在这次测试中,我的服务完美无缺。

但是,如果我添加另一个发送消息的客户端应用程序(2 个应用程序向服务发送消息)应用程序崩溃并抛出超时异常(大多数情况下是 SendTimeOut)。

第二次测试每秒的消息量低于第一次测试,因为我在请求之间使用了 Thread.Sleep(),所以我认为问题在于发送请求的应用程序数量多于请求数量,但我我不确定。

你知道为什么会出现这些问题吗?

我的服务和客户端应用程序编码如下:

服务合同:

[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

Try out setting throttling settings explicitly for server WCF service:

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

BTW, Which ConcurrrencyMode / InstanceMode is used for WCF service?

Suggested for read:

于 2012-11-23T22:05:13.990 回答
0

确保每次通话后都在客户端代理上调用 .Close()。您可以通过一个代理实例进行多次调用,但在完成客户端调用后始终使用 .Close() 。

于 2013-03-14T16:55:14.847 回答