设置ConcurrencyMode.Multiple后WCF服务仍单线程处理请求问题
问题分析与解决方案
咱们来拆解你遇到的这个WCF并发问题,其实是两个关键细节导致服务端没能并发处理请求:
核心原因
1. 客户端复用单一通道实例,请求被迫串行发送
WCF的Channel实例不是线程安全的,当多个线程同时调用同一个通道的方法时,框架会自动串行化这些调用,避免线程冲突。你当前的客户端代码里,所有线程都共用同一个IServer channel,这直接导致请求只能一个接一个发送到服务端,自然触发不了服务端的并发处理逻辑。
2. BasicHttpBinding的默认行为限制并发
你使用的basicHttpBinding是无会话绑定,默认启用了HTTP Keep-Alive。这意味着客户端的所有请求会复用同一个HTTP连接,而HTTP 1.1协议在单一连接上的请求是串行处理的——哪怕服务端配置了多并发,也没办法同时处理同一个连接上的多个请求。
具体解决方案
方案一:客户端每个线程创建独立的通道实例
修改客户端代码,让每个线程都拥有自己的通道实例,这样每个请求都会通过独立通道发送,服务端就能并发处理了:
// 客户端Main方法修改如下 static void Main() { const int threadCount = 6; int value = 0; for (int i = 0; i < threadCount; i++) { new Thread(state => { int n; lock (lockObj) { value++; n = value; } // 每个线程独立创建通道工厂和通道 using (var factory = new ChannelFactory<IServer>("defaultEndPoint")) { IServer channel = factory.CreateChannel(); Console.WriteLine("Send value = {0}, Time = {1}", n, DateTime.Now.TimeOfDay); n = channel.GetResult(n); Console.WriteLine("Response value = {0}, Time = {1}", n, DateTime.Now.TimeOfDay); // 显式关闭通道 ((IClientChannel)channel).Close(); } }).Start(); } Console.ReadLine(); }
方案二:服务端改用支持会话的绑定(如wsHttpBinding)
如果想保留客户端复用通道的模式,可以把服务端的绑定换成wsHttpBinding——它默认支持会话,每个会话会分配独立的处理线程,能更好地支持并发:
修改服务端配置文件的端点绑定:
<endpoint contract="Server.IServer" binding="wsHttpBinding" address=""/>
客户端配置同步更新为wsHttpBinding即可(如果是单独配置文件,重新生成客户端代理就能自动适配)。
方案三:调整BasicHttpBinding的并发配置(可选)
如果必须使用basicHttpBinding,可以修改绑定配置,禁用Keep-Alive并增加最大连接数:
<bindings> <basicHttpBinding> <binding name="ConcurrentBasicHttpBinding" keepAliveEnabled="false" maxConnections="100"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> </binding> </basicHttpBinding> </bindings>
然后在服务端点引用这个自定义绑定:
<endpoint contract="Server.IServer" binding="basicHttpBinding" bindingConfiguration="ConcurrentBasicHttpBinding" address=""/>
修改后的预期效果
服务端控制台会输出不同的ThreadId,说明多线程并发处理请求:
In: 1, Time: 11:30:13.1234567, ThreadId: 12 In: 2, Time: 11:30:13.1244568, ThreadId: 13 In: 3, Time: 11:30:13.1254569, ThreadId: 14 ... Out: 1, Time: 11:30:14.1234567, ThreadId: 12 Out: 2, Time: 11:30:14.1244568, ThreadId: 13 ...
客户端的响应也会集中在同一时间返回,而不是每隔1秒才收到一个。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

