netcore+dapper 造成的内存泄漏问题排查总结

3/3/2023 4:38:48 PM
1593
0

背景:系统上线后缓存缓慢的不停的增长。

系统采用net5框架,用dapper连接数据库,内存不断的慢慢增长。

解决:首先获得 dump文件。具体参考官方文档 https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/debug-memory-leak

 

查看dotnet下的所有进程,以获取进程 ID

dotnet-counters ps

或者直接使用以下命令得到 ID

ps -ef|grep  '端口号/服务名'

现使用 dotnet-counters 工具检查托管内存的使用情况。 --refresh-interval 指定两次刷新之间的秒数:

dotnet-counters monitor --refresh-interval 1 -p 4807

4807  是进程ID

实时输出应如下所示:

Press p to pause, r to resume, q to quit.
    Status: Running

[System.Runtime]
    # of Assemblies Loaded                           118
    % Time in GC (since last GC)                       0
    Allocation Rate (Bytes / sec)                 37,896
    CPU Usage (%)                                      0
    Exceptions / sec                                   0
    GC Heap Size (MB)                                  4
    Gen 0 GC / sec                                     0
    Gen 0 Size (B)                                     0
    Gen 1 GC / sec                                     0
    Gen 1 Size (B)                                     0
    Gen 2 GC / sec                                     0
    Gen 2 Size (B)                                     0
    LOH Size (B)                                       0
    Monitor Lock Contention Count / sec                0
    Number of Active Timers                            1
    ThreadPool Completed Work Items / sec             10
    ThreadPool Queue Length                            0
    ThreadPool Threads Count                           1
    Working Set (MB)                                  83

 

重点介绍此行:

GC Heap Size (MB)                                  4

启动后,可以看到托管堆内存为 4 MB。

现在,转到 URL https://localhost:5001/api/diagscenario/memleak/20000。

请注意,内存使用量已增加到 30 MB

GC Heap Size (MB)                                 30

通过监视内存使用情况,可以确定内存正在增长或泄漏。 下一步是收集内存分析的适当数据。

生成内存转储

分析可能的内存泄漏时,需要访问应用的内存堆来分析内存内容。 查看对象之间的关系,可以创建关于为什么内存未释放的理论。 常见的诊断数据源是 Windows 上的内存转储或 Linux 上的等效核心转储。 若要生成 .NET Core 应用程序转储,可使用 dotnet-dump 工具。

使用之前启动的示例调试目标,运行以下命令以生成 Linux 核心转储:

dotnet-dump collect -p 4807

结果是位于同一文件夹中的核心转储。

Writing minidump with heap to ./core_20190430_185145
Complete

你可以在控制台上使用命令继续分析内存使用情况。生成核心转储后,请使用 dotnet-dump 工具分析转储。参考  https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/debug-memory-leak

dotnet-dump analyze core_20190430_185145

也可以将此文件下载到本地,新手推荐下载到本地进行分析

将core_20190430_185145文件下载下来,用vs打开

 

 点击调试托管内存 按钮即可

经过简单的设置你可以看到占用内存比较多的对象,查看实例可以看到更详细的信息

 

 

还可以设置内存占用大小比例,参考 https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector#high-memory-percent

本次排查结果:  dapper 默认会记录所有sql语句,因为我偷懒在sql中直接拼接了 datetime.now ,所以每个查询的sql语句都是唯一的,这就造就了 dapper记录了大量的sql语句字符串

dapper缓存问题参考:https://www.cnblogs.com/ITWeiHan/p/11614704.html

全部评论



提问