同主机Windows服务短时间大量请求后无法访问另一服务报超时错误
问题产生原因
故障时telnet能正常响应,说明TCP层端口监听、网络连通性完全正常,问题出在WCF应用层的配置缺陷与代码实现问题,核心触发点有三个:
- WCF默认限流阈值过低被打满:你使用的
NetTcpBinding所有限流参数默认值都面向低并发场景:服务端默认最大并发会话数、最大并发调用数均为10,客户端/服务端最大连接池连接数默认也为10。短时间发起大量请求时,WCF应用层的请求处理队列、连接池会被瞬间占满,新到的请求无法进入处理流程直接触发超时。而telnet仅完成TCP三次握手,不进入WCF的应用层处理队列,所以不会受这个限流影响,表现为telnet正常但服务调用超时。 - 客户端代码存在严重的连接资源泄漏:你当前的代码仅在调用结束后关闭了
ChannelFactory,但完全没有关闭CreateChannel()生成的客户端代理通道。WCF的客户端通道持有独立的连接与会话资源,如果不显式关闭,这些资源会等待GC最终回收,期间会一直占用客户端连接池配额、服务端的会话配额,高并发场景下很快就会把有限的配额占满,触发新请求超时。另外你每次调用都新建ChannelFactory本身就是错误实践:ChannelFactory是重开销的线程安全对象,反复创建销毁会产生大量临时连接与内存开销,进一步加剧资源耗尽的概率。 - TCP端口资源耗尽:短时间大量短连接调用会产生大量处于
TIME_WAIT状态的TCP连接,Windows Server 2012默认动态端口范围、TIME_WAIT等待时长(默认2分钟)如果没做优化,很容易出现端口耗尽,新的连接无法建立触发超时。
排查步骤
- 故障发生时在服务器执行
netstat -ano | findstr "<服务B的监听端口>",统计当前连接数:如果ESTABLISHED、TIME_WAIT状态的连接数远大于10,基本可以确认是WCF限流阈值打满或者连接泄漏问题。 - 给服务B开启WCF跟踪日志,故障后查看日志:如果存在大量
QuotaExceededException异常,可直接确认是WCF限流配置不足。 - 打开服务器的事件查看器,定位到「Windows日志-应用程序」,筛选来源为
System.ServiceModel的错误日志,WCF配额超限、通道故障类问题都会在这里留下明确记录。 - 持续观察服务A、服务B进程的句柄数、线程数、内存占用:如果指标随调用量持续上涨不回落,可确认存在连接资源泄漏。
解决方法
代码层面修复
- 将
ChannelFactory改为单例复用,不要每次调用都新建,ChannelFactory<T>本身是线程安全的,全局复用可以减少90%以上的重复创建开销。 - 每次调用完成后必须正确关闭客户端代理通道,不能仅关闭工厂。注意WCF通道在出错状态下直接调用
Close()会抛出异常,需要调用Abort()释放资源,修正后的调用代码示例:
// 全局单例初始化ChannelFactory,仅在服务启动时执行一次 private static readonly ChannelFactory<IBServiceProxy> _factory = new ChannelFactory<IBServiceProxy>( new ServiceEndpoint( ContractDescription.GetContract(typeof(IBServiceProxy)), new NetTcpBinding(SecurityMode.None) { // 客户端绑定配置同步调整 MaxConnections = 1000, SendTimeout = TimeSpan.FromSeconds(30), OpenTimeout = TimeSpan.FromSeconds(10), ReceiveTimeout = TimeSpan.FromSeconds(30) }, new EndpointAddress($"net.tcp://127.0.0.1:{hostPort}/B") // 同机调用优先用回环地址,减少网络栈开销 ) ); // 单次调用逻辑 IBServiceProxy proxy = null; try { proxy = _factory.CreateChannel(); proxy.Send(); ((ICommunicationObject)proxy).Close(); } catch { ((ICommunicationObject)proxy)?.Abort(); throw; }
配置层面优化
- 调整服务B的
NetTcpBinding配置,调高限流参数,参考配置:MaxConnections="1000"- 服务行为里设置
maxConcurrentCalls="1000"、maxConcurrentSessions="1000"、maxConcurrentInstances="1000",具体数值可以根据实际峰值并发量调整。
- 如果开启了Net.Tcp端口共享服务,需要同步调整端口共享服务的最大连接数配额,默认值同样很低,会成为瓶颈。
系统层面优化
- 同机调用不要使用物理网卡IP,统一用
127.0.0.1回环地址,减少网络层转发开销。 - 调整TCP参数优化短连接性能:
- 打开注册表定位到
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,新建DWORD值TcpTimedWaitDelay,设为十进制30,将TIME_WAIT等待时间从默认120秒缩短到30秒。 - 新建DWORD值
MaxUserPort,设为十进制65534,扩大动态端口可用范围。 - 修改后重启服务器生效。
- 打开注册表定位到
内容的提问来源于stack exchange,提问作者Veysel Kurhan
相关产品推荐
相关产品推荐

