C# WCF服务是否使用多个线程来处理传入请求?
如何确保WCF服务使用线程池中的线程来处理传入消息 目前,像“returnnull;”这样的简单方法调用另一个请求正在处理时大约需要45秒 以下是我如何注释我的服务类: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 { ...
[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完全处于最大状态,那么线程池管理器的试探法将使其不愿意向线程池中添加更多线程
然而,还有两个潜在问题:
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]);