Linux中的DotNet Core 2.1 ho积内存

时间:2018-12-20 12:18:39

标签: linux asp.net-core memory-leaks kubernetes garbage-collection

我有一个Websocket服务器,它可以在几天内ho积内存,直到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服务器:

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

在禁用GC Server之前,该服务用于更快地增加内存。现在要花两周的时间才能达到512Mb。

按请求/响应方式使用ASP.NET Core的其他服务不会显示此问题。它使用Websockets,每个连接通常持续10分钟左右...所以我想与该连接有关的所有内容都可以轻松保留到第二代。

enter image description here 请注意,有两个Pod显示相同的行为,然后由于进行了内存转储而在内存使用中突然掉了一个(绿色)。

enter image description here

在进行内存转储期间,pod没有重新启动: enter image description here

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

堆:

(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

对此行为有任何解释吗?

2 个答案:

答案 0 :(得分:1)

问题是与RabbitMQ的连接。因为我们使用的是排序活动频道,所以RabbitMQ.Client的“自动重新连接”功能使许多有关无效频道的状态保持不变。由于不需要“自动重新连接”功能的“特权”,因此我们关闭了此配置,并且一切正常开始工作。这很痛苦,但是我们基本上必须设置Windows部署并使用Windows工具(在这种情况下为Jetbrains dotMemory)执行常规的内存分析过程。使用lldb根本没有效果。

答案 1 :(得分:0)

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

但是您应该在Kubernetes最佳实践中做两件事:

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

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