2015-12-10 37 views
4

我们有一个Asp.net 4.5 mvc webapi,它有大约100个应用程序域,每个包含一个扩展名。IIS垃圾收集与许多应用程序域挂起

现在我们不时地挂着api。即使只返回一个字符串的状态api没有回应,也没有一个路由正在响应。

当它挂起时,该网站有大约120个线程(这是很正常的)和大约12 GB的RAM(这是不寻常的高)。

当我们做一个内存转储时,我们可以看到该网站是总是在垃圾回收中间

大多数情况下,我们发现大多数线程都处于堆栈,处理应用程序域之间的序列化并等待GC。 我们也有很多序列化,例如应用程序域通信以及与某些Redis缓存的组合

等待5分钟时的事件不会结束。是否有任何已知的与许多应用程序域有关的垃圾回收问题?

由于该网站托管在IIS中,后台GC应始终处于活动状态。

当我看到在GC性能计数器的时间我可以看到GC几乎总是运行

enter image description here

我可以看到,当网站挂了不断的40%的时间在GC enter image description here

当站点处于这种状态时,我也可以看到内存永久略有增加。

任何提示什么测试或尝试改进?

将运行时升级到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 
+0

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

回答

0

一些进一步的调查后的AppDomain没有的原因。 我希望这可以节省其他人很多搜索:-)

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

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

也有关于如何优化GC代码,可以帮助