C# WCF服务是否使用多个线程来处理传入请求?

C# WCF服务是否使用多个线程来处理传入请求?,c#,.net,multithreading,wcf,threadpool,C#,.net,Multithreading,Wcf,Threadpool,如何确保WCF服务使用线程池中的线程来处理传入消息 目前,像“returnnull;”这样的简单方法调用另一个请求正在处理时大约需要45秒 以下是我如何注释我的服务类: [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] public partial class MyService : IMyService { ...

如何确保WCF服务使用线程池中的线程来处理传入消息

目前,像“returnnull;”这样的简单方法调用另一个请求正在处理时大约需要45秒

以下是我如何注释我的服务类:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
    public partial class MyService : IMyService {
...
}
但是当我在任务管理器中观察这个过程时,它似乎使用了固定数量的线程。即使在负载下


以下是我的服务行为:

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

InstanceContextMode和ConcurrencyMode是两个独立的概念,但它们之间有一定程度的相互作用——在不久前的某个深度上

WCF调用在IO线程池线程上处理。假设您没有执行类似于
ConcurrencyMode.Single
InstanceContextMode.Single
的操作,它将序列化服务中的每个调用,线程池管理器将尝试平衡线程数与工作速率

如果并发请求的数量可以由5个线程提供服务,那么这就是它将使用的数量。您可能会看到,线程池可以跟上工作速率和您可以看到的线程数。您可以非常高兴地使用比内核更多的线程,因为只要线程不是纯CPU绑定的,当先前运行的线程启动IO时,操作系统就可以通过将线程切换到CPU来获得吞吐量。如果CPU完全处于最大状态,那么线程池管理器的试探法将使其不愿意向线程池中添加更多线程

然而,还有两个潜在问题:

  • 当通过同一代理存在多个并发出站请求时,基于会话的绑定可以在客户端阻塞。你不知道;不要说如何生成多个请求,因此这可能是一个问题
  • 在.NET4之前,默认的最大并发请求数为16,默认的并发会话数为10,因此您可能会看到节流开始起作用。这些值在.NET 4中已提高,但您没有说明使用的是.NET的哪个版本

  • InstanceContextMode=SIngle意味着:您有一个singleton—只有一个服务实例。不是很容易扩展!ConcurrencyMode=Multiple意味着singleton可以同时为多个服务请求提供服务——但这也意味着,您的服务实现代码必须是100%线程安全的——这不是一项容易的任务!我建议使用
    InstanceContextMode.PerCall
    ConcurrencyMode.Single
    ——这样,每个传入的WCF请求都会获得自己的服务类实例来处理请求。WCF运行时可以处理多个并发请求,您的代码很容易编写。可能重复:有时InstanceContextMode=Single是可以的-例如,当API是无状态的并且只是转发调用时。不需要创建多个服务实例。例如,返回队列长度之类的内容或将数据提交到处理队列的方法调用。。。编写100%线程安全的代码是我们中一些人的标准行为——不是每个人都是脚本小子。@marc_s请看我的问题。我在.NET4上。在ASP.NET网站上,每当我需要从服务请求某些内容时,我都会创建新的代理。看来我们走的路是对的,这可能是个问题。您是否在代理上呼叫close?这是您的问题-您已达到MaxConcurrentSessions油门的饱和点。每个请求都必须等待上一个会话超时。关闭或重用代理,您应该会看到吞吐量增加-我在这里写了关于会话的博客,我的配置中有
    maxConcurrentCalls=“100”
    。你真的认为我会同时接到100个电话吗?不,正如我在评论中所说的那样,你正在达到会话油门。创建并使用新代理时,它将建立会话。除非关闭代理,否则默认情况下会话将保持活动状态20分钟。当您在不关闭代理的情况下使用站点时,最终您达到了100 x内核数的会话限制(在.NET4上的默认值)。新呼叫仅在某些会话超时时才传入
    <?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>
    
    ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(String.Format("net.tcp://{0}/", _bindAddress)));
                myserviceHost.Open();
                Console.WriteLine(myserviceHost.BaseAddresses[0]);