.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就用上面的結果(每個都試下,因為不是每一個都有你想要的結果)
其中一個結果如下:

這樣的數據結構,就可以找到接口了,暫時到這,下次再續。

浙公網安備 33010602011771號