Azure 应用服务高内存消耗网络核心

Posted

技术标签:

【中文标题】Azure 应用服务高内存消耗网络核心【英文标题】:Azure App Services High Memory Consumption Net Core 【发布时间】:2018-07-21 23:05:29 【问题描述】:

伙计们! 我是管理在高负载下工作的服务器应用程序的新手,并且面临一个问题。我的应用程序(.NET Core 2.1,使用 MVC 控制器)用作简单的 REST 服务(客户端从 Sql Server DB 获取和设置数据)。工作负载约为每秒 100 个请求(我只使用一个实例)。问题是 GC 永远不会(从字面上看永远不会)发生,内存使用量攀升至 ~2 GB,因此每 30-60 分钟我的应用程序就会重新启动。大多数情况下,重启是静默发生的,但有时会记录以下 OOM 异常之一

Received an exception: [Exception of type 'System.OutOfMemoryException' was thrown.], [   at System.Collections.Generic.List`1.set_Capacity(Int32 value)
at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
   at System.Collections.Generic.List`1.AddWithResize(T item)
   at System.PinnableBufferCache.AgePendingBuffers()
   at System.PinnableBufferCache.Restock(Object& returnBuffer)
   at System.PinnableBufferCache.Allocate()
   at System.Threading.Overlapped..ctor()
   at System.Threading.PreAllocatedOverlapped..ctor(IOCompletionCallback callback, Object state, Object pinData)
   at System.Net.Sockets.SocketAsyncEventArgs.InitializeInternals()
   at System.Net.Sockets.SocketAsyncEventArgs..ctor(Boolean flowExecutionContext)
   at System.Net.Sockets.SocketAsyncEventArgs..ctor()
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketSender..ctor(Socket socket, PipeScheduler scheduler)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketConnection..ctor(Socket socket, MemoryPool`1 memoryPool, PipeScheduler scheduler, ISocketsTrace trace)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.RunAcceptLoopAsync()
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.UnbindAsync()
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StopAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StopAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
   at WillHeroServer.Program.Main(String[] args) in C:\Projects\MyApp\src\MyApp\Program.cs:line 17], System.Private.CoreLib

 

Received an exception: [Exception of type 'System.OutOfMemoryException' was thrown.], [   at System.Net.Sockets.Socket.GetOrCreateAcceptSocket(Socket acceptSocket, Boolean checkDisconnected, String propertyName, SafeCloseSocket& handle)
   at System.Net.Sockets.Socket.AcceptAsync(SocketAsyncEventArgs e)
   at System.Net.Sockets.Socket.AcceptAsync(Socket acceptSocket)
   at System.Net.Sockets.SocketTaskExtensions.AcceptAsync(Socket socket)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.RunAcceptLoopAsync()
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.UnbindAsync()
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StopAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StopAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
   at WillHeroServer.Program.Main(String[] args) in C:\Projects\MyApp\src\MyApp\Program.cs:line 17], System.Net.Sockets

我以为我造成了导致这种行为的内存泄漏,但我没有。我什至制作并部署了一个空的应用程序(没有路由,什么都没有),用于处理这些请求数量和返回 BadRequest 的内存消耗仍然将内存提升到上一个级别并重置应用程序(尽管,重置之间的延迟有点长)。应用服务计划设置为 B2(2x 内核,3.5 GB RAM)。我尝试升级到 B3,但没有解决问题,所以我回滚了。

1) 为什么在我的情况下一个空的应用程序永远不会释放内存?

2) Kestrel 可以处理这些请求吗?

3) 我是否遗漏了 Azure 中的一些设置,或者它看起来很好,我应该只创建几个应用实例?

【问题讨论】:

您已经玩过 Kestrel 限制配置了吗? - 即 .UseKestrel(options => options.Limits.MaxConcurrentConnections = 100; options.Limits.MaxConcurrentUpgradedConnections = 100; .... @Avanish,是的,我做到了。不幸的是没有运气:( 【参考方案1】:

听起来您可能有内存泄漏。这就是内存泄漏的定义,当内存增长并且 GC 无法回收它时。

这通常意味着您正在加载到内存中的对象仍然有一个引用并且仍然是“根”(有一个引用)。您需要确保已正确处置所有对象 (IDisposable)。

此外,您从网络上读取的任何内容都可能大于您的可用内存。这种情况的可能性较小。

但是,将 GC 行为更改为单线程并不是解决问题的可行方案。

【讨论】:

【参考方案2】:

你试过了吗:

<PropertyGroup> 
   <ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>

?

Reducing .NET Core Memory Usage

我遇到了一个问题,这个问题似乎有效。您可以 google 搜索不同的 GC。

【讨论】:

恐怕这没有帮助 我强烈建议不要这样做,因为它会将垃圾收集器从多线程更改为单线程。这将对您的 GC 以及您的应用程序产生非常明显的负面性能影响。特别是当涉及到 Gen 2 GC 和任何潜在的 LOH 碎片时。阅读更多 - docs.microsoft.com/en-us/dotnet/standard/garbage-collection/…

以上是关于Azure 应用服务高内存消耗网络核心的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin - Sqlite.net 内存消耗非常高

Java 内存消耗很高并且还在增长

如何降低IIS应用程序池内存消耗

AngularJS异常高的内存消耗

Azure技术13-高可用--Azure负载平衡器