IIS 垃圾收集挂起许多应用程序域
IIS Garbage Collection hangs with many appdomains
我们有一个 Asp.net 4.5 mvc webapi,它有大约 100 个应用域,每个域都包含一个扩展。
现在我们不时遇到 api 的问题。甚至没有一个路由在响应状态 api,只有 returns 一个字符串不响应。
当它挂起时,站点有大约 120 个线程(这是很正常的)和大约 12 GB 的 RAM(这是不寻常的高)。
当我们进行内存转储时,我们可以看到站点总是处于垃圾回收过程中。
大多数时候我们看到大多数线程挂在堆栈中,代码处理应用程序域之间的序列化并等待 GC。
我们也有很多序列化,比如应用程序域通信和结合一些 redis 缓存
事件在等待大约 5 分钟时挂起没有结束。是否存在与许多应用程序域相关的垃圾收集的任何已知问题?
由于网站托管在 IIS 中,因此后台 GC 应始终处于活动状态。
当我查看 GC 性能计数器中的时间时,我发现 GC 几乎总是 运行
我可以看到,当站点挂起时,其在 gc 中的持续时间为 40%
当网站处于这种状态时,我还可以看到内存在永久性地略有增加。
关于测试或尝试改进什么的任何提示?
将运行时升级到 4.5.2 时是否可能有好处?
像这样:
ntdll!NtWaitForSingleObject+a
KERNELBASE!WaitForSingleObjectEx+94
clr!CLREventWaitHelper2+38
clr!CLREventWaitHelper+1f
clr!CLREventBase::WaitEx+70
clr!SVR::gc_heap::wait_for_gc_done+55
clr!SVR::WaitLonger+9e
clr!SVR::GCHeap::Alloc+224
clr!JIT_New+142
[[HelperMethodFrame]]
mscorlib_ni!System.Runtime.Serialization.ObjectManager.RegisterFixup(System.Runtime.Serialization.FixupHolder, Int64, Int64)+d1
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()+128
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(System.Runtime.Remoting.Messaging.HeaderHandler, System.Runtime.Serialization.Formatters.Binary.__BinaryParser, Boolean, Boolean, System.Runtime.Remoting.Messaging.IMethodCallMessage)+db
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler, Boolean, Boolean, System.Runtime.Remoting.Messaging.IMethodCallMessage)+1bf
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeObject(System.IO.MemoryStream)+f8
mscorlib_ni!System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.FixupForNewAppDomain()+de8a4e
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[], System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage, System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage ByRef)+33
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(System.Object[])+92
clr!CallDescrWorkerInternal+83
clr!CallDescrWorkerWithHandler+4a
clr!DispatchCallDebuggerWrapper+1f
clr!DispatchCallSimple+88
clr!ThreadNative::InternalCrossContextCallback+2ea
[[ContextTransitionFrame]]
[[HelperMethodFrame_PROTECTOBJ] (System.Threading.Thread.InternalCrossContextCallback)] System.Threading.Thread.InternalCrossContextCallback(System.Runtime.Remoting.Contexts.Context, IntPtr, Int32, System.Threading.InternalCrossContextDelegate, System.Object[])
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatch(Byte[], System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage, System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage ByRef)+a0
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)+15d
mscorlib_ni!System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(System.Runtime.Remoting.Messaging.IMessageSink, System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Contexts.ArrayWithSize, System.Threading.Thread, System.Runtime.Remoting.Contexts.Context, Boolean)+8c
mscorlib_ni!System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(System.Runtime.Remoting.Messaging.IMethodCallMessage, Boolean, Int32)+22c
mscorlib_ni!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)+1f4
clr!CTPMethodTable__CallTargetHelper3+12
clr!CallTargetWorker2+74
clr!CTPMethodTable::OnCall+1fb
clr!TransparentProxyStub_CrossContextPatchLabel+a
[[TPMethodFrame] (SR.BusPortal.Providers.Contract.Common.IAdapterSearcher.SearchAsync)] SR.BusPortal.Providers.Contract.Common.IAdapterSearcher.SearchAsync(SR.BusPortal.Providers.Contract.Common.AdapterSearchParameters)
SR.BusPortal.Search.Steps.SearchStepOneWay`2+<SearchOneWayAsync>d__3[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].MoveNext()+73
经过进一步调查,appdomains 不是原因。
我希望这可以为其他人节省很多搜索 :-)
我们在 webapi 进程中有一个很大的 Memory GraphDatabase(它使用了大约 30GB 的 RAM)。结果我们的webapi工程和同进程的graphdatabase出现问题,GC一直没成功结束进程。使用非异步 gc 问题更好,但有时有点迟钝。
将此数据库分离到其自己的服务后,此行为再也不会发生。
还有很多关于如何为 GC 优化代码的帖子,可能会有帮助
我们有一个 Asp.net 4.5 mvc webapi,它有大约 100 个应用域,每个域都包含一个扩展。
现在我们不时遇到 api 的问题。甚至没有一个路由在响应状态 api,只有 returns 一个字符串不响应。
当它挂起时,站点有大约 120 个线程(这是很正常的)和大约 12 GB 的 RAM(这是不寻常的高)。
当我们进行内存转储时,我们可以看到站点总是处于垃圾回收过程中。
大多数时候我们看到大多数线程挂在堆栈中,代码处理应用程序域之间的序列化并等待 GC。 我们也有很多序列化,比如应用程序域通信和结合一些 redis 缓存
事件在等待大约 5 分钟时挂起没有结束。是否存在与许多应用程序域相关的垃圾收集的任何已知问题?
由于网站托管在 IIS 中,因此后台 GC 应始终处于活动状态。
当我查看 GC 性能计数器中的时间时,我发现 GC 几乎总是 运行
我可以看到,当站点挂起时,其在 gc 中的持续时间为 40%
当网站处于这种状态时,我还可以看到内存在永久性地略有增加。
关于测试或尝试改进什么的任何提示?
将运行时升级到 4.5.2 时是否可能有好处? 像这样:
ntdll!NtWaitForSingleObject+a
KERNELBASE!WaitForSingleObjectEx+94
clr!CLREventWaitHelper2+38
clr!CLREventWaitHelper+1f
clr!CLREventBase::WaitEx+70
clr!SVR::gc_heap::wait_for_gc_done+55
clr!SVR::WaitLonger+9e
clr!SVR::GCHeap::Alloc+224
clr!JIT_New+142
[[HelperMethodFrame]]
mscorlib_ni!System.Runtime.Serialization.ObjectManager.RegisterFixup(System.Runtime.Serialization.FixupHolder, Int64, Int64)+d1
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()+128
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(System.Runtime.Remoting.Messaging.HeaderHandler, System.Runtime.Serialization.Formatters.Binary.__BinaryParser, Boolean, Boolean, System.Runtime.Remoting.Messaging.IMethodCallMessage)+db
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream, System.Runtime.Remoting.Messaging.HeaderHandler, Boolean, Boolean, System.Runtime.Remoting.Messaging.IMethodCallMessage)+1bf
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeObject(System.IO.MemoryStream)+f8
mscorlib_ni!System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.FixupForNewAppDomain()+de8a4e
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[], System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage, System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage ByRef)+33
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(System.Object[])+92
clr!CallDescrWorkerInternal+83
clr!CallDescrWorkerWithHandler+4a
clr!DispatchCallDebuggerWrapper+1f
clr!DispatchCallSimple+88
clr!ThreadNative::InternalCrossContextCallback+2ea
[[ContextTransitionFrame]]
[[HelperMethodFrame_PROTECTOBJ] (System.Threading.Thread.InternalCrossContextCallback)] System.Threading.Thread.InternalCrossContextCallback(System.Runtime.Remoting.Contexts.Context, IntPtr, Int32, System.Threading.InternalCrossContextDelegate, System.Object[])
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatch(Byte[], System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage, System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage ByRef)+a0
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)+15d
mscorlib_ni!System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(System.Runtime.Remoting.Messaging.IMessageSink, System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Contexts.ArrayWithSize, System.Threading.Thread, System.Runtime.Remoting.Contexts.Context, Boolean)+8c
mscorlib_ni!System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(System.Runtime.Remoting.Messaging.IMethodCallMessage, Boolean, Int32)+22c
mscorlib_ni!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)+1f4
clr!CTPMethodTable__CallTargetHelper3+12
clr!CallTargetWorker2+74
clr!CTPMethodTable::OnCall+1fb
clr!TransparentProxyStub_CrossContextPatchLabel+a
[[TPMethodFrame] (SR.BusPortal.Providers.Contract.Common.IAdapterSearcher.SearchAsync)] SR.BusPortal.Providers.Contract.Common.IAdapterSearcher.SearchAsync(SR.BusPortal.Providers.Contract.Common.AdapterSearchParameters)
SR.BusPortal.Search.Steps.SearchStepOneWay`2+<SearchOneWayAsync>d__3[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].MoveNext()+73
经过进一步调查,appdomains 不是原因。 我希望这可以为其他人节省很多搜索 :-)
我们在 webapi 进程中有一个很大的 Memory GraphDatabase(它使用了大约 30GB 的 RAM)。结果我们的webapi工程和同进程的graphdatabase出现问题,GC一直没成功结束进程。使用非异步 gc 问题更好,但有时有点迟钝。
将此数据库分离到其自己的服务后,此行为再也不会发生。
还有很多关于如何为 GC 优化代码的帖子,可能会有帮助