Does WCF Service use multiple threads to process i

2019-04-08 14:08发布

问题:

How can I ensure that a WCF service uses threads from a ThreadPool to process incoming messages?

At the moment simple method invocation like 'return null;' takes about 45 seconds while another requests are processing

Here is how I have annotated my service class:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
    public partial class MyService : IMyService {
...
}

But when I'm watching the process in task manager it seems to be using a constant number of threads. Even under load.


public ActionResult SelectDatabase(string param)
        {
            if (!String.IsNullOrEmpty(param))
            {
            try
            {
                MyServicece svc = new MyService();
                Database[] dbsArray = svc.GetDatabases(param);
                if (depsArray != null)
                    ViewData["depsArray"] = depsArray;

                return View();
            }
            catch (Exception exc)
            {
                // log here                
                return ActionUnavailable();
            }
        }

Here is my service behavior:

<?xml version="1.0"?>
<configuration>
  <runtime>

  </runtime>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="100" />
    </connectionManagement>
  </system.net>
  <system.serviceModel>
    <diagnostics performanceCounters="Default" />
    <bindings>      
      <netTcpBinding>
        <binding sendTimeout="00:02:00" receiveTimeout="00:02:00" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
          <security mode="None">           
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <behaviors>
      <endpointBehaviors>
        <behavior name="CrossDomainServiceBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="MyService.MyServiceBehavior">
          <serviceThrottling maxConcurrentCalls="100"   maxConcurrentInstances="100" maxConcurrentSessions="100" />
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MyService.MyServiceBehavior" name="MyService.MyService">
        <endpoint address="MyService" binding="netTcpBinding" contract="AService.IAServ"  isSystemEndpoint="false" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="MyService.MyServiceBehavior" name="MyService.MyServiceAdmin">
        <endpoint address="MyServiceAdmin" binding="netTcpBinding" contract="MyService.IMyServiceAdmin"  isSystemEndpoint="false" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />        
      </service>
    </services>
  </system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

Here is how I create service instance:

ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(String.Format("net.tcp://{0}/", _bindAddress)));
            myserviceHost.Open();
            Console.WriteLine(myserviceHost.BaseAddresses[0]);

回答1:

InstanceContextMode and ConcurrencyMode are separate concepts but which have a level of interplay - I blogged about this in some depth a while back

WCF calls are processed on IO threadpool threads. Assuming you haven't done something like ConcurrencyMode.Single, InstanceContextMode.Single which will serialize every call into the service the threadpool manager will try to balance the number of threads to the rate of work.

If the number of concurrent requests can be serviced by 5 threads then that's how many it will use. You may be seeing that the threadpool can keep up with the rate of work with the number of threads you can see. You can quite happily use more threads than cores with effect because, as long as the threads are not purely CPU bound, the OS can gain throughput by switching threads onto the CPU when the previously running thread starts IO. If the CPU is completely max'd out then the heuristics of the threadpool manager will make it reticent to add more threads into the thread pool

However, there are another couple of potential issues:

  1. Session based bindings can block on the client side while there are multiple concurrent outbound requests through the same proxy. You don;t say how you are generating the multiple requests so this may be an issue;
  2. You may also be seeing throttling kicking in as, prior to .NET 4 the default max number of concurrent requests was 16 and default number of concurrent sessions was 10. These values have been raised in .NET 4 but you don't say which version of .NET you are using