我有一个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分钟左右...所以我想与该连接有关的所有内容都可以轻松保留到第二代。
请注意,有两个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
对此行为有任何解释吗?
答案 0 :(得分:1)
问题是与RabbitMQ的连接。因为我们使用的是排序活动频道,所以RabbitMQ.Client的“自动重新连接”功能使许多有关无效频道的状态保持不变。由于不需要“自动重新连接”功能的“特权”,因此我们关闭了此配置,并且一切正常开始工作。这很痛苦,但是我们基本上必须设置Windows部署并使用Windows工具(在这种情况下为Jetbrains dotMemory)执行常规的内存分析过程。使用lldb根本没有效果。
答案 1 :(得分:0)
免责声明:我不是.NET向导。
但是您应该在Kubernetes最佳实践中做两件事:
为您的应用程序定义合理的资源限制。如果应用程序不需要超过200MB的内存,请定义资源限制以防止应用程序占用所有可用的主机内存。但是请注意,获取可用内存的Unix API无法处理该进程拥有的cgroup,并且无论您的cgroup说什么,总是会输出主机内存。
告诉您的应用此资源限制是什么。似乎您的应用没有“感觉到需要”来释放内存,因为有很多内存。几乎所有应用程序和框架都具有一个开关,以定义要消耗的最大内存。告诉您的应用此限制,它将“查看”内存压力并执行完整的GC(我想这里可能是问题所在)