.net core内存泄漏排查

背景:我们是一个.net 9 的WebApi程序ConsumeApi,主要做rabbimq的消费。部署后所在程序在任务管理器中越来越大撑爆了服务器的内存消耗报警

参照:油管视频

.NET 线上内存溢出排查:使用dotnet-dump方法

步骤

  1. 在本地vs2022上跑起程序,程序为ReportApi

  2. 进入命令行,安装命令dotnet-counter(同理安装dotnet-dump)

    dotnet tool install --global dotnet-counters
    
  3. 查看内存情况

    dotnet-counters ps
    

    可展示出一些可排查程序的列表,显示有对应的端口号及程序名(5580 ConsumeApi xxx)

    dotnet-counters monitor -p 5580
    

    可展示出对应的内存使用及回收情况可借助ai解读观察到对应指标的变化

    参数英文名 参数含义中文 当前值 值的大小分析
    dotnet.assembly.count ({assembly}) 程序加载的程序集数量 181 加载的程序集较多,可能依赖较多,代码库较大或依赖复杂
    dotnet.exceptions ({exception}) .NET异常总计 7403 异常数很高,需关注异常情况,可能存在大量数据库异常
    error.type : IOException IO异常数量 1 IO异常很少,磁盘/文件访问较稳定
    error.type : MySqlException MySQL异常数量 7,403 数据库异常极多,建议重点排查数据库连接或SQL问题
    dotnet.gc.collections ({collection}) gc.heap.generation : gen0 gen0收集次数 65 gen0收集频繁,但不算太多,短生命周期对象创建不算繁重
    dotnet.gc.collections ({collection}) gc.heap.generation : gen1 gen1收集次数 78 gen1收集次数略多于gen0,可能有较多中短生命周期对象
    dotnet.gc.collections ({collection}) gc.heap.generation : gen2 gen2收集次数 2 gen2收集很少,长生命周期的垃圾对象很少产生,大致正常
    dotnet.gc.heap.total_allocated (By) 堆总分配字节数 3,044,800,000字节≈2.83GB 分配总量较大,内存使用较多,注意潜在内存溢出风险
    dotnet.gc.last_collection.heap.fragmentation.size (By) gen0 gen0堆碎片大小 3,475,288 gen0有较大碎片,表明短生存周期对象频繁分配释放,可能影响性能
    … gen1 gen1堆碎片大小 24 极小,说明碎片整理良好
    … gen2 gen2堆碎片大小 3,720 偏小,属于正常范围
    … loh 大对象堆(LOH)碎片 128 很小,LOH分配较为集中,无严重碎片
    … poh 永久对象堆(POH)碎片 488 很小,说明POH碎片问题基本可忽略
    dotnet.gc.last_collection.heap.size (By) gen0 gen0堆大小 3,731,784 较小,符合gen0的特性
    … gen1 gen1堆大小 1,072 很小
    … gen2 gen2堆大小 5,053,664 较大,长生命周期对象较多,持续占用内存
    … loh 大对象堆(LOH)大小 425,440 约415KB,正常,未见异常大对象分配
    … poh 永久对象堆(POH)大小 152,800 约149KB,正常
  4. 在启用dotnet-dump排查,找到对应程序,同上面dotnet-counters

    dotnet-dump ps
    
  5. 生成分析文件,生成dmp文件

    C:\Users\zyd>dotnet-dump collect -p 5580
    Writing full to C:\Users\zyd\dump_20250607_194542.dmp
    Complete
    
  6. 分析文件

    C:\Users\zyd>dotnet-dump analyze dump_20250607_194542.dmp
    
  7. 查看托管堆的情况,会展示dmp文件里托管堆里的对象和个数【按从少到多排列】,基本上拉到最下面数量特别多的对象去排查

    dumpheap -stat
    

    显示

    7ff7efbd1120  2,423   348,912 SqlSugar.DbColumnInfo
    7ff7ee7a96c8  3,384   351,936 System.Reflection.RuntimeMethodInfo
    7ff7ee79b420  2,580 1,377,451 System.Byte[]
    7ff7ee69bf40 25,779 2,546,692 System.String
    Total 134,441 objects, 11,656,563 bytes
    
  8. 可以看到SqlSugar.DbColumnInfo对象特别多有348,912个,我们进一步查看它的所有的对象

    dumpheap -mt 7ff7efbd1120
    

    显示

    xxx
    01cce1d19508     7ff7efbd1120            144
    01cce1d19790     7ff7efbd1120            144
    01cce1d19a18     7ff7efbd1120            144
    01cce1d19c68     7ff7efbd1120            144
    01cce1d19eb8     7ff7efbd1120            144
    
  9. 选择一个分析,可大致看到它引用的地方

    gcroot 01cce1d192a0