【.Net Core】分析.net core在linux下内存占用过高问题--持续更新
https://www.cnblogs.com/zhenglisai/p/14751677.html
现象
随着程序运行,内存占用率越来越高,直到触发linux的OOM,程序被杀死。
分析工具
运行环境:.net core 3.1(微软的分析工具要求最低3.0,无法分析2.1的core程序,需要先改为core 3.1才能分析)
linux:ubuntu 18
分析工具:dotnet-counters, dotnet-dump
工具的安装见:https://docs.microsoft.com/zh-cn/dotnet/core/diagnostics/dotnet-counters
分析过程
1,获取要分析进程的pid
使用top或者ps等等工具,获取程序的pid
对于docker环境,如果没有安装top命令,可以使用如下安装
apt-get install procps
2,查看内存使用情况(我这里pid为13156)
dotnet-counters monitor -p 13156
从结果来看,GC中的Gen2占用了较多的内存,理论上,不应该有很多的Gen2,我们需要分析一下Gen2里面到底是什么?
Gen0,Gen1,Gen2以及LOH的区别,以及.net core内存管理机制,见:
https://docs.microsoft.com/en-us/aspnet/core/performance/memory?view=aspnetcore-5.0
3,获取进程的dump文件
dotnet-dump collect -p 13156
说明:要使用这条命令获取dump,如果在docker中,需要提供docker的--private参数,如果是在AWS的ECS中使用的Fargate模式运行,则不支持此参数。需要在EC2上运行。
此命令会在当前目录生成一个dump文件
4,分析dump文件
dotnet-dump analyze core_20210510_054712
# 分析gen2中的内容,每个命令的参数以及和含义,可以使用help查看
dg gen2
从结果来看,有很多string类型的数据在gen2中,以及mysql的一些数据,我们打开看看具体是什么内容
看输出,有很多一样的内容,我们随便打开一个看看
可以看到内容就是数据库的返回数据
同样的方法,我们看看哪些string里面都是什么
有非常多的对象,我们也是随便打开一个看看内容
看着像是web的打印
总结
获取dump文件
dotnet-dump collect <pid>
分析dump文件
dotnet-analyze xxxxx
获取gen2或者其他的内存数据
dg gen2 | gen1 | gen1 | genloh
查看内存数据类型
dumpheap -mt xxxxxx
查看内存数据的具体内容
do xxxxxx
通过具体内容,配合开发人员定位代码问题
-------------------------------------------
2021-5-11 更新
再说明一下我们这边的运行环境,以及代码中用到的相关服务
我们正式程序运行在AWS基于Fargate的ECS上,容器配置为0.5vCPU, 512MB内存,.net core程序版本为2.1,数据库查询使用sqlsugar,aws服务用到了Dynamodb和SNS
问题就是程序运行大约1天就出现OOM,导致容器重启。
下面是我们排查问题的过程
Round 1:将core从2.1升级到3.1
原因:根据微软的说法,3.0以后优化了core在linux下以及容器中的性能,降低了内存占用,详见下面的连接。
https://devblogs.microsoft.com/dotnet/using-net-and-docker-together-dockercon-2019-update/
说明:2.1升级到3.1还是有很多地方需要修改的,微软这方面做的就不够好,但是3.1升级5.0据说改动不大,这里要感谢我们的开发同学积极配合修改了代码。
结论:内存增长速度为原来的一半。
内存增长速度变慢了,但是仍然在增长,没有解决根本问题。
Round 2:调整GC模式,从默认的Server GC调整为WorkStation GC
原因:WorkStaionGC会使用更少的内存,回收的更频繁,但是性能可能会稍差一下,根据微软的说法,在docker环境中还是推荐使用WorkStaion GC模式,两种GC的对比,以及推荐详见下文:
https://docs.microsoft.com/en-us/aspnet/core/performance/memory?view=aspnetcore-3.1#workstation-gc-vs-server-gc
结论:内存增长速度又降低了一半,但是仍然在增长,还是没有解决根本问题
Round 3:Gen2中的内存到底是什么?
原因:既然内存不停的在涨,而且通过分析工具可以看到主要是GC中的Gen2部分在增长,按照微软的说法内存中的垃圾数据根据时间的长短,依次存入Gen0, Gen1, Gen2。而且Gen1和Gen2是由core进行垃圾回收的,不需要我们干预,那么Gen2中的内容到底是什么?为什么一直没有被回收?
这一部分就是上面的文章内容,通过以上方法我们已经知道Gen2中的内存主要是变量、数据库查询结果、console控制台打印。奇了怪了,为什么这些东西会在内存里不释放?
关于core的内存管理以及GC原理,见下面的文章
https://docs.microsoft.com/en-us/aspnet/core/performance/memory?view=aspnetcore-3.1
结论:找到了内存中的数据,但是不解这些数据为什么没有被回收
Round 4:关闭这些打印看看
原因:既然Gen2中存在大量的控制台打印,那么我如果关闭控制台打印呢?是不是就没有这部分的内存占用了
结论:没啥作用,内存仍然在不停的增长
Round 5:是不是数据库工具有问题?
原因:既然内存中有大量的数据库查询结果,那么是不是因为我们用了sqlsugar导致的?sqlsugar本身有什么缓存的机制?
我们查了sqlsugar的官方,sqlsugar确实支持二级缓存,但是我们没有用上,详见官方文档:
https://www.donet5.com/home/Doc?typeId=1214
为此,我们直接删除了sqlsugar部分代码,不查询数据库了,直接写死在代码里返回。然后开始跑压力测试(这时候接口已经没有业务逻辑了)
结论:没啥用,内存还在增长
Round 6:放大招了,写一个空接口,没有任何逻辑,直接返回固定字符串
原因:做减法不行,我们开始做加法,从0开始写接口,一点点功能添加,看看到底添加到哪一步的时候,导致内存增加
结论:老实了,内存终于不增长了(准确的说增长的非常缓慢,一晚上增加了0.2%的内存)
至少说明core本身在docker环境下运行,没有明显的内存泄露问题,问题应该出在代码逻辑上
###############################
今天到此为止,等我们后续的尝试出了结果再更新,希望我们的测试过程对大家有些参考。
相关文章
- [Linux] linux awk命令详解
- Linux的基本使用
- linux(centos8):安装分布式事务服务seata(file单机模式,seata 1.3.0/centos 8.2)
- Linux 下安装Rider 和 Net core SDK
- 【学习总结】快速上手Linux玩转典型应用-第6章-linux常用命令讲解
- linux(centos8):配置docker的cgroup driver为systemd
- linux如deepin manjaro对笔记本电脑电池的伤害解决方案:TLP:一个可以延长 Linux 笔记本电池寿命的高级电源管理工具
- Linux中cat、more、less、tail、head命令的使用示例
- Win10下访问linux的ext4分区文件并拷贝
- 【Linux 内核】调度器 ⑧ ( 进程优先级源码 includelinuxschedprio.h | 进程分类 | 实时进程 | 普通进程 | 进程优先级数值 | 0 ~ 99 实时进程 )
- 【Linux 内核】Linux 内核源码目录说明 ③ ( lib 目录 | LICENSES 目录 | mm 目录 | net 目录 | samples 目录 | scripts 目录 )
- Linux命令: 在线使用linux命令环境
- .Net——使用.net内置处理程序处理自己定义节点Demo
- L68.linux命令每日一练 -- 第十章 Linux网络管理命令 -- ping和traceroute
- L49.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- fdisk和partprobe
- L40.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- useradd和usermod
- linux命令之busybox microcom,串口调试命令
- linux C access
- Linux安装Python2.7.9
- LEADTOOLS 22-23 .Net/NetCore/JS/JAVA/Win/Linux
- Linux没有显卡如何保存图片单细胞分析 scanpy下查看GPU信息和使用情况 查看显卡信息 lspci | grep -i vga 使用nvidia GPU查看Linux服务器有gpu
- net core HTTP Error 500.31 - Failed to load ASP.NET Core runtime HTTP Error 500.30