.net core在linux docker部署,内存异常分析,分析工具:dotnet-dump
老项目为.net 4.6,部署在iis,设置的32位,消耗内存基本稳定在500mb左右,但是升级为.net 6,部署在linux docker上以后,内存消耗异常,记录一下
docker stats查看, 用户模块占10g
一,创建dump文件
注:执行/usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.25/createdump 1 这句的时候,会导致程序无法访问,内存越大,保存时间越长,请选择合适的时间进行此操作。
[root@WEB1 zwsec]# docker exec -it base bash
root@68a12d966fa4:/src# find / -name createdump
/usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.25/createdump
root@68a12d966fa4:/src# /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.25/createdump 1
[createdump] Gathering state for process 1 dotnet
[createdump] Writing minidump with heap to file /tmp/coredump.1
[createdump] Written 13254832128 bytes (3236043 pages) to core file
[createdump] Target process is alive
[createdump] Dump successfully written
root@68a12d966fa4:/src# exit
exit
[root@WEB1 zwsec]# docker cp base:/tmp/coredump.1 /data1/app/server/test_dump/coredump.1
[root@WEB1 zwsec]# cd /data1/app/server/test_dump/
[root@WEB1 test_dump]# ls
coredump.1
二、分析dump文件
dotnet-dump
工具依赖dotnet的sdk,如果宿主机中安装了sdk可以直接在宿主机中分析;
如果不想污染宿主机环境可以拉取一个sdk镜像mcr.microsoft.com/dotnet/sdk,创建一个临时环境用于分析。
1,创建一个用于分析的临时容器
需要把用于存放coredump.1文件的目录挂载到容器,或者自己cp进去。
创建好容器之后需要安装dotnet-dump
工具
[root@WEB1 zwsec]# docker run --security-opt seccomp=unconfined --name test --rm -it -v /data1/app/server/test_dump:/tmp/coredump mcr.microsoft.com/dotnet/sdk
Unable to find image 'mcr.microsoft.com/dotnet/sdk:latest' locally
latest: Pulling from dotnet/sdk
fd674058ff8f: Pull complete
d92ceca2d7b5: Pull complete
408b46bb4d4d: Pull complete
e9dfe0944a0c: Pull complete
3425c4117635: Pull complete
e4513f6c2cfb: Pull complete
5e118823fce1: Pull complete
66fb1dfc2c9d: Pull complete
683a16faa7de: Pull complete
Digest: sha256:3fcf6f1e809c0553f9feb222369f58749af314af6f063f389cbd2f913b4ad556
Status: Downloaded newer image for mcr.microsoft.com/dotnet/sdk:latest
root@d99cf52da4ed:/# cd /tmp/coredump
root@d99cf52da4ed:/tmp/coredump# ls
coredump.1
root@d99cf52da4ed:/tmp/coredump# dotnet tool install -g dotnet-dump
Tools directory '/root/.dotnet/tools' is not currently on the PATH environment variable.
If you are using bash, you can add it to your profile by running the following command:
cat << \EOF >> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:/root/.dotnet/tools"
EOF
You can add it to the current session by running the following command:
export PATH="$PATH:/root/.dotnet/tools"
You can invoke the tool using the following command: dotnet-dump
Tool 'dotnet-dump' (version '9.0.553101') was successfully installed.
root@d99cf52da4ed:/tmp/coredump# export PATH="$PATH:/root/.dotnet/tools"
root@d99cf52da4ed:/tmp/coredump#
2,分析内存泄漏
命令:
1.dotnet-dump analyze coredump.1
2.dumpheap -stat 找到堆上的对象信息(注:此命令第一次执行时会消耗很久时间,请泡一杯茶耐心等候,如果服务器会自动断开连接的,建议下载到一台不会断开连接的机器进行分析,因为这里可能在没有分析出来连接就断开了)
3.dumpheap -mt <mt> 列出所有与<mt>结构对应的对象,一般我都会找string对象的mt,看看里面大size的string对象是有哪些
4.do <address> 查看对象详细信息
5.gcroot -all <address> 一般我也是找string地址,看看对象引用
root@d99cf52da4ed:/tmp/coredump# dotnet-dump analyze coredump.1
Loading core dump: coredump.1 ...
Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
Type 'quit' or 'exit' to exit the session.
> dumpheap -stat
7f19789cbdd0 808,824 71,176,512 System.RuntimeMethodInfoStub
7f197e149d88 758,432 78,876,928 Newtonsoft.Json.Linq.JProperty
7f197cffb878 7,107,012 170,568,288 System.WeakReference<Microsoft.Extensions.DependencyInjection.ServiceProvider>
7f1977244ab8 350,296 179,511,302 System.Char[]
7f19789f5598 1,818,443 307,396,110 System.Byte[]
7f197d74f1f0 325,913 433,410,924 <unknown_type_7f197d74f1f0>
7f19771bd2e0 4,481,237 626,510,840 System.String
563ee4af1ea0 497,037 1,051,396,144 Free
Total 33,543,157 objects, 4,234,311,341 bytes
此时我们看到一个很大的string,使用第三个命令:dumpheap -mt {上面红框第一个值} 注:这一步第一次执行的时候也会需要点时间,请耐心等待
由于结果太多,没有截到标题,第一列是address,最后一列是size
结果出来了,可以看到有很多占内存一样大的字符串,此时需要用到第四个命令 do {第一列的address}
注:如果是比较小的string,红框部分就会显示该string的内容,但是这个太大了,无法显示
此时百度,谷歌,bing都查询无果,然后敲下了每个软件都会有的一个命令 help
在所有命令中一个命令一个命令试过之后,找到两个命令 dq <address> du <address>
先执行dq <address> ,会得到一群类似adress的东西
再du <adress> 注:这里的address就用上面的结果(每个都试下,因为不是每一个都有你想要的结果)
其中一个结果如下:
这样的数据结构,就可以找到接口了,暂时到这,下次再续。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)