C# IIS垃圾回收与许多AppDomain挂起

C# IIS垃圾回收与许多AppDomain挂起,c#,asp.net,.net,garbage-collection,appdomain,C#,Asp.net,.net,Garbage Collection,Appdomain,我们有一个Asp.net 4.5 mvc webapi,它有大约100个应用程序域,每个域包含一个扩展 现在,我们不时会遇到api挂起的问题。没有一条路由响应,即使是只返回字符串的状态api也没有响应 当它挂起时,站点有大约120个线程(这是很正常的)和大约12GB的RAM(这是非常高的) 当我们做内存转储时,我们可以看到在垃圾回收的中间,站点是“强”总是“< /强”。 大多数时候,我们看到大多数线程挂在一个堆栈中,代码处理应用程序域之间的序列化,并等待GC。 我们也有很多序列化,比如应用程序域

我们有一个Asp.net 4.5 mvc webapi,它有大约100个应用程序域,每个域包含一个扩展

现在,我们不时会遇到api挂起的问题。没有一条路由响应,即使是只返回字符串的状态api也没有响应

当它挂起时,站点有大约120个线程(这是很正常的)和大约12GB的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 
ntdll!NtWaitForSingleObject+a
内核库!WaitForSingleObjectEx+94
clr!CLREventWaitHelper2+38
clr!CLREventWaitHelper+1f
clr!CLREventBase::WaitEx+70
clr!SVR::gc\u堆::等待\u gc\u完成+55
clr!SVR::WaitLonger+9e
clr!SVR::GCHeap::Alloc+224
clr!JIT_新+142
[[HelperMethodFrame]]
mscorlib_ni!System.Runtime.Serialization.ObjectManager.RegisterFixup(System.Runtime.Serialization.FixUplder,Int64,Int64)+d1
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.\u BinaryParser.Run()+128
mscorlib_ni!System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(System.Runtime.Remoting.Messaging.HeaderHandler,System.Runtime.Serialization.Formatters.Binary.\u 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.Channel.CrossAppDomainSerializer.DeserializeObject(System.IO.MemoryStream)+f8
mscorlib_ni!System.Runtime.Remoting.Messaging.SnockedMethodCallMessage.FixupForNewAppDomain()+de8a4e
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(字节[],System.Runtime.Remoting.Messaging.SnockedMethodCallMessage,System.Runtime.Remoting.Messaging.SnockedMethodReturnMessage ByRef)+33
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.DotTransitionDispatchCallback(System.Object[])+92
clr!CallDeScreworkerInternal+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.Channel.CrossAppDomainSink.DotTransitionDispatch(字节[],System.Runtime.Remoting.Messaging.走私方法调用消息,System.Runtime.Remoting.Messaging.走私方法调用消息ByRef)+a0
mscorlib_ni!System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)+15d
mscorlib_ni!System.Runtime.Remoting.Proxy.RemotingProxy.CallProcessMessage(System.Runtime.Remoting.Messaging.IMessage,System.Runtime.Remoting.Messaging.IMessage,System.Runtime.Remoting.Context.ArrayWithSize,System.Threading.Thread,System.Runtime.Remoting.Context.Context,布尔)+8c
mscorlib_ni!System.Runtime.Remoting.Proxy.RemotingProxy.InternalInvoke(System.Runtime.Remoting.Messaging.IMethodCallMessage,布尔值,Int32)+22c
mscorlib_ni!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef,Int32)+1f4
clr!CTPMethodTable_u_调用目标服务器3+12
clr!CallTargetNetworker2+74
clr!CTPMethodTable::OnCall+1fb
clr!TransparentProxyStub_CrossContextPatchLabel+a
[[TPMethodFrame](SR.BusPortal.Providers.Contract.Common.IAdapterSearcher.SearchAsync)]SR.BusPortal.Providers.Common.IAdapterSearcher.SearchAsync(SR.BusPortal.Providers.Contract.Common.AdapterSearchParameters)
SR.BusPortal.Search.Steps.SearchStepOneWay`2+d_uuuuuu3[[System.\uuuuuuu Canon,mscorlib],[System.\uuuuuu Canon,mscorlib]].MoveNext()+73

经过进一步调查,appdomains不是原因。 我希望这可以为其他人节省大量搜索时间:-)

在webapi过程中,我们有一个大内存GraphDatabase(它使用了大约30GB的RAM)。因此,我们的webapi项目和同一进程中的graphdatabase出现了问题,GC从未成功地结束该进程。使用非异步gc时,问题会更好,但有时会有点滞后

将此数据库分离到其自己的服务后,此行为再也不会发生


还有很多关于如何优化GC代码的帖子,这可能会有所帮助

我认为每个AppDomain都应该是自己的沙箱。因此,一个AppDomain中的垃圾收集不应冻结另一个AppDomain。使用RedGate或Jetbrain的内存工具查看哪些对象占用内存。在web应用程序的大对象堆中有多少对象,您会感到惊讶。当您向另一个web服务发出请求时,通常是大字节的数据数组。看看是否可以汇集任何资源。