繁体   English   中英

DotNet Core 2.1在Linux中囤积内存

[英]DotNet Core 2.1 hoarding memory in Linux

我有一个websocket服务器,在几天内囤积内存,直到Kubernetes最终杀死它。 我们用prometheous-net监控它。

# dotnet --info

Host (useful for support):
  Version: 2.1.6
  Commit:  3f4f8eebd8

.NET Core SDKs installed:
  No SDKs were found.

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

但是当我远程连接并进行内存转储(使用createdump )时,突然内存丢失......没有服务停止,重新启动或丢失任何连接的用户。 请参见图中的绿线。

我可以在图表中看到,GC正在各代人中定期收集。

使用以下命令禁用GC Server:

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

在禁用GC Server之前,用于以更快的速度增长内存的服务。 现在进入512Mb需要两周时间。

在请求/响应方式上使用ASP.NET Core的其他服务不会显示此问题。 这使用Websockets,每个连接通常持续大约10分钟......所以我猜想与连接相关的一切都很容易存在到第2代。

在此输入图像描述 请注意,有两个pod,显示相同的行为,然后由于获取内存转储,一个(绿色)突然在内存消息中下降。

在此输入图像描述

在获取内存转储期间,pod未重新启动: 在此输入图像描述

没有连接丢失或重新启动。

堆:

(lldb) eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00007F8481C8D0B0
generation 1 starts at 0x00007F8481C7E820
generation 2 starts at 0x00007F852A1D7000
ephemeral segment allocation context: none
         segment             begin         allocated              size
00007F852A1D6000  00007F852A1D7000  00007F853A1D5E90  0xfffee90(268430992)
00007F84807D0000  00007F84807D1000  00007F8482278000  0x1aa7000(27947008)
Large object heap starts at 0x00007F853A1D7000
         segment             begin         allocated              size
00007F853A1D6000  00007F853A1D7000  00007F853A7C60F8  0x5ef0f8(6222072)
Total Size:              Size: 0x12094f88 (302600072) bytes.
------------------------------
GC Heap Size:            Size: 0x12094f88 (302600072) bytes.
(lldb)

免费对象:

(lldb) dumpheap -type Free -stat
Statistics:
              MT    Count    TotalSize Class Name
00000000010c52b0   219774     10740482      Free
Total 219774 objects

这种行为有什么解释吗?

问题是与RabbitMQ的连接。 因为我们使用了实时频道,所以RabbitMQ.Client的“自动重新连接”功能保留了很多关于死信道的状态。 我们关闭了这个配置,因为我们不需要“自动重新连接”功能的“特权”,一切都开始正常工作。 这是一个痛苦,但我们基本上不得不设置Windows部署并使用Windows工具(在本例中为Jetbrains dotMemory)执行常规的内存分析过程。 使用lldb根本没有效率。

免责声明:我不是.NET向导。

但是你应该对Kubernetes最佳实践做两件事:

  1. 为您的应用定义合理的资源限制。 如果应用程序不需要超过200MB的内存,则定义资源限制以防止应用程序占用所有可用的主机内存。 但请注意,获取可用内存的Unix API无法处理该进程所具有的cgroup,并且无论cgroup说什么,都始终输出主机内存。

  2. 告诉你的应用这个资源限制是什么。 看起来你的应用程序没有“感觉有必要”释放内存,因为有很多。 几乎所有应用程序和框架都有一个开关来定义要消耗的最大内存。 告诉你的应用这个限制,它会“看到”内存压力并执行一个完整的GC(我猜这可能是问题)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM