WCF服务停止处理呼叫15秒

azu*_*ric 6 c# wcf multithreading windows-services webhttpbinding

我在我的一个WCF服务中遇到了一个奇怪的行为.这项服务工作良好约1.5年,但几周后它显示出某种"停电"(不幸的是我无法发布图像因为我是新来的).

虽然仍有来电,但来电/秒降至0."停电"总是15秒.在这15秒之后,处理排队的呼叫.它不能与网络相关,因为90%的呼叫来自同一服务器上的另一个WCF服务,并且没有其他服务(总共10个)受此行为的影响.服务本身确实继续工作,如计算内部资源,进行数据库更新等.不会增加内部工作的执行时间.这发生在大约18-25分钟,但停电总是15秒.

OS

Windows Server 2012

WCF作为Windows服务运行

WCF配置:

InstanceContextMode = InstanceContextMode.PerCall,

ConcurrencyMode = ConcurrencyMode.Multiple,

UseSynchronizationContext = false,

IncludeExceptionDetailInFaults = true

Binding = WebHttpBinding

并发节流设置:

MaxConcurrentCalls = 384,

MaxConcurrentInstances = 2784,

MaxConcurrentSessions = 2400

我已经做了一些调查:

  1. WCF油门设置

我在服务发生的确切时间内完全转储了服务.ConcurrentCalls和ConcurrentSessions都没用完.转储没有显示可能导致问题的任何异常.

  1. MAX TCP Conenction

监控活动TCP连接远非其限制.

  1. 交换机中的端口中继

由于没有来电,甚至来自本地服务(使用localhost),我很确定它与网络无关.

  1. 加载问题

低负载(见下文)和高负载(传入呼叫的​​5倍)会出现此问题.其频率不会根据负载而变化.我还尝试在我的登台系统上重现行为,每秒约600-1000次呼叫.我设法将服务带入一个状态,我发送更多来电/秒,因为服务可以处理.突出的电话增加了,在某些时候,服务当然崩溃了.但这种行为从未出现过.

  1. 线程池耗尽

当服务运行50个线程并且还有200个线程时,会出现此问题.虽然没有更多可用线程,但会出现错误消息.

我已经没有可能引起这种行为的事情了.我认为,它可能是GC阻塞线程,因为该服务在RAM中使用大约10GB.它是一种内存缓存服务.或者它可能是操作系统(Windows Server 2012)或与Windows服务本身相关的东西.

有没有人自己面对这样的事情,或者有人有另外的想法会导致什么?

编辑:现在我可以发布图片:

在此输入图像描述

编辑: GC堆转储(感谢usr)

在此输入图像描述

我看到近50%(总共70%,包括相关参考文献)是由一本大字典引起的.2700万条目(基于内存转储堆).我将专注于重构它.里面有很多未使用的物品.也许这会有所帮助.

另外,我将从msdn 添加GC.WaitForFullGCApproach方法,以查看当服务停止处理传入请求时GC是否正在运行.

当我知道更多时,我会告诉你.

编辑: GC统计(包括停电14秒)

•CLR Startup Flags: CONCURRENT_GC
•Total CPU Time: 42.662 msec
•Total GC CPU Time: 2.748 msec
•Total Allocs : 1.524,637 MB
•MSec/MB Alloc : 1,802 msec/MB
•Total GC Pause: 2.977,2 msec
•% Time paused for Garbage Collection: 19,4%
•% CPU Time spent Garbage Collecting: 6,4%
•Max GC Heap Size: 11.610,333 MB
•Peak Process Working Set: 14.917,915 MB
•Peak Virtual Memory Usage: 15.326,974 MB
Run Code Online (Sandbox Code Playgroud)

这只是暂停3秒.无论如何,这不应该那么高,我会重构内存存储.但它并没有解释15秒:(

编辑:在周末我做了以下事情:

  1. 已安装最新Windows更新(上次更新时间是2个月前)

  2. 重新启动Windows服务器

  3. 重构了2700万个对象的in-mem存储.我设法将使用的内存从11GB减少到6-8GB(这是相当多的).那里很旧的代码;)

到目前为止,这个问题并未再次发生(现在大约运行17小时).这导致我假设GC导致暂停服务或某些操作系统相关问题导致该行为.

我猜这个问题根本没有"解决",并且会在某个时刻重新出现,导致数据会随着时间的推移而增加.

感谢大家花时间在这上面.我将继续调查转储并尝试详细了解发生的情况.我会及时向大家发布.

Pet*_*art 0

如果中断是足够可预测的,您可以在中断期间与windbg+SOS连接并且:

  • 停电期间暂停服务两次
  • 每次运行!threads~*e!dumpstack显示线程状态和堆栈

如果您有 100 个线程在 15 秒内没有执行任何生产操作,这应该反映在堆栈中 - 幸运的是,您的 100 个线程中的大部分是:

  1. 卡在您的方法之一中(检查每个线程的“当前帧”)
  2. 陷入 WCF 方法中
  3. 执行*WaitFor*呼叫
  4. 执行睡眠/延迟/IO 完成调用