WCF服务中不明原因的线程创建和句柄计数增加

时间:2014-08-22 21:56:35

标签: wcf service clr threadpool

我们在具有32个内核的Server 2008 R2 Amazon EC2实例上的IIS上托管了多个WCF服务。我们使用的是.NET Framework 4.5.2版。手头的问题是无法解释的句柄数增加 - 我们的一些服务在活动超过一天后累积了数十万个打开的句柄(当我使用第三方工具强制垃圾收集时,句柄数量下降到大约2k) 。 在调查这个时,我创建了一个没有功能的简单服务,并在IIS下启动它。没有客户端请求此服务。在一小时内,在服务流程下有20k +处理。用procmon查看服务的进程,我可以看到20多个线程退出的爆发,然后线程创建,每40秒左右。然后我将服务的应用程序池从.NET Framework V4.0切换到v2.0并再次启动该服务;手柄数量在整个小时内从大约500个打开手柄移动。我无法在我的几台机器上重现这个问题(不是在亚马逊上)。我知道CLR 4.0中有重大的线程池更改 - http://msdn.microsoft.com/en-us/magazine/ff960958.aspx,但我不知道为什么我看到1)线程创建活动没有客户端请求或正在执行的工作由服务和2)为什么线程句柄和相关的事件句柄没有被释放。

2 个答案:

答案 0 :(得分:1)

我最近使用.NET服务遇到了这个问题(在带有.NET 4.5.1的Server 2012 R2上的IIS中托管)。闲置时,它会积累> 30,000个手柄。在WinDbg中使用!htrace我可以看到所有句柄都在这个堆栈中创建:

Call Site
clr!Thread::CreateNewOSThread+0x7f
clr!Thread::CreateNewThread+0x90
clr!ThreadpoolMgr::CreateUnimpersonatedThread+0xc7
clr!ThreadpoolMgr::MaybeAddWorkingWorker+0x113
clr!ManagedPerAppDomainTPCount::SetAppDomainRequestsActive+0x24
clr!ThreadpoolMgr::SetAppDomainRequestsActive+0x2a
clr!ThreadPoolNative::RequestWorkerThread+0x2b
mscorlib_ni!System.Threading.ThreadPoolWorkQueue.Dispatch()
mscorlib_ni![ContextTransitionFrame: 0000002b15e4ef28] 
clr!CallDescrWorkerInternal+0x83
clr!CallDescrWorkerWithHandler+0x4a
clr!MethodDescCallSite::CallTargetWorker+0x380
clr!QueueUserWorkItemManagedCallback+0x2a
clr!ManagedThreadBase_DispatchInner+0x2d
clr!ManagedThreadBase_DispatchMiddle+0x6c
clr!ManagedThreadBase_DispatchOuter+0x75
clr!ManagedThreadBase_DispatchInCorrectAD+0x15
clr!Thread::DoADCallBack+0x25b
clr!ManagedThreadBase_DispatchInner+0x69
clr!ManagedThreadBase_DispatchMiddle+0x6c
clr!ManagedThreadBase_DispatchOuter+0x75
clr!ManagedThreadBase_FullTransitionWithAD+0x2f
clr!ManagedPerAppDomainTPCount::DispatchWorkItem+0xe3
clr!ThreadpoolMgr::ExecuteWorkRequest+0x64
clr!ThreadpoolMgr::WorkerThreadStart+0x2b6
clr!Thread::intermediateThreadProc+0x7d
KERNEL32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d

每次调用CreateNewOSThread都会创建1个Thread句柄和4个Event句柄,这些句柄没有被清理(线程会完成运行,但句柄会一直存在)。我从未追踪到向线程池添加任务的内容,但我注意到的是,由于服务“空闲”,GC从未被调用过。

由于某种原因,当允许工作线程退出时,线程池管理器不会处理句柄,而是依赖于垃圾收集器来执行它。

作为测试,我添加了一种方法来手动调用服务上的垃圾收集器。在观察到手柄的线性增加之后,我在服务上踢了一个GC,看着手柄数量下降到正常水平。

答案 1 :(得分:0)

在托管一个WCF服务的w3wp.exe实例中,.NET 4中至少存在3个AppDomain,一个名为SharedAppDomains,其中包含20多个.net框架程序集,另一个名为Default,最后一个名为Default像/ LM / W3Svc这样的东西......一些时髦的名字,它包含你的WCF应用程序集以及一些直接的依赖项。什么工具告诉你,只有一个app域没有包含其他程序集?最简单的方法是以管理员的身份运行Process Explorer ,并检查w3wp.exe实例的.NET程序集。

尽管如此,即使你的WCF在没有响应即将发出的请求的情况下运行空闲,w3wp.exe也没有空闲运行,因为它是一个负责许多内务处理任务的托管进程。在Windows 7上的IIS 7的.net 4应用程序池上的.NET 4.5.1上的Hello World WCF服务中,w3wp.exe的线程数在44-47之间跳转。内存使用情况以及其他资源数据基本稳定。

您提到的问题仅发生在AWS计算机上,而不是您的其他计算机上。因此,您最好通过运行Process Explorer 作为管理员找出所有加载的应用程序域及其程序集,并比较您自己PC上的w3wp.exe实例列表,并挑出一些常见的嫌疑人,可以做比预期更多的工作。当然,可能是w3wp.exe遭到入侵并做了狗狗的事情,但是,在这个阶段,首先检查程序集和应用程序域。这不是答案,但是,SO的评论区域对评论的长度有限制。所以希望这是开始检查事情的地方。