我在我的一个WCF服务中遇到了一个奇怪的行为。这项服务工作良好约1.5年,但几周后它显示出某种类型的“停电”#34; (不幸的是我无法发布图片,因为我在这里很新。)
虽然仍有来电,但来电/秒降至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
我已经做了一些调查:
我在服务发生的确切时间内完全转储了服务。 ConcurrentCalls和ConcurrentSessions都没用完。转储没有显示可能导致问题的任何异常。
监控活动的TCP连接远非它的限制。
由于没有来电,即使是本地服务(使用localhost),我也很确定它与网络无关。
低负载(见下文)以及高负载(传入呼叫的5倍)会出现此问题。其频率不会根据负载而变化。我还尝试在我的登台系统上重现行为,每秒约600-1000次呼叫。我设法将服务带入一个状态,我发送更多来电/秒,因为服务可以处理。突出的电话增加了,在某些时候,服务当然崩溃了。但这种行为从未出现过。
当服务运行50个线程并且还有200个线程时,会出现问题。虽然没有更多可用线程,但会出现关于此的错误消息。
我已经没有可能引起这种行为的事情了。我认为,它可能是GC阻塞线程,因为该服务在RAM中使用大约10GB。它是一种内存缓存服务。或者它可能是操作系统(Windows Server 2012)或与Windows服务本身相关的东西。
有没有人自己面对这样的事情,或者是否有人知道可能导致这种情况的原因?
修改:现在我可以发布图片了:
编辑: GC堆转储(感谢usr)
我看到近50%(总共70%,包括相关参考文献)是由一本大字典引起的。 2700万条目(基于内存转储堆)。我将专注于重构它。里面有很多未使用的物品。也许这会有所帮助。
此外,我将从msdn添加GC.WaitForFullGCApproach Method,以查看当服务停止处理传入请求时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
那"只是"暂停3秒。无论如何,那不应该那么高,我会重构内存存储。但它根本没有解释15秒:(
编辑:在周末期间,我做了以下事情:
已安装的最新Windows更新(上次更新时间为2个月前)
重新启动Windows服务器
重构了2700万个对象的in-mem存储。我设法将使用的内存从11GB减少到6-8GB(这是相当多的)。那里很旧的代码;)
到目前为止,问题并没有再次发生(现在大约运行17小时)。这导致我假设GC导致服务暂停或某些操作系统相关问题导致了这种行为。
我猜这个问题不是解决了#34;在某些时候会重新出现,导致数据会随着时间的推移而增加。
感谢大家花时间在这上面。我将继续调查转储并尝试详细了解发生的情况。我会告诉你的。
答案 0 :(得分:0)
如果中断足够可预测,您可以在停电期间连接windbg + SOS并且:
!threads
和~*e!dumpstack
以显示线程状态和堆栈如果你有100个线程在15秒内没有做任何工作,这个应该反映在堆栈中 - 幸运的是你的100个线程的大部分是:
*WaitFor*
来电