文章目录
前言
1. 生成dump文件
2. 读取dump文件的三个方式
通过windbg+sos读取
dotnet自带的dotnet-dump进行读取
使用lldb+sos读取(推荐)
3.分析
前言
在本地开发调试的时候,基于VS的工具能方便看出内存泄露的信息:

在这里插入图片描述
但到了线上,一般都是在linux环境中,并且服务运行在docker上,这时出现内存泄露,CPU异常等情况,就无法直接调试,只能把docker中在允许的服务内存下来dump信息,进行分析,思路上就这几步: 

  1. 把运行时的内存给dump下来,传到本地
  2. 能正确读取出dump信息
  3. 分析原因

把运行时的内存给dump下来,传到本地
能正确读取出dump信息
分析原因
1. 生成dump文件
生成dump文件,依赖createdump工具,这个工具是.net core runtime自带的,所以只要运行在.net core上的项目, 就可以直接使用该工具。

进行容器内部,dockername 可以通过docker ps得到
docker exec -it dockername /bin/bash

找到工具对应的目录:
find /usr/share -name createdump
在这里插入图片描述

通过上面的路径执行createdump,就会保存当前容器在运行时的信息。
1代表容器内要保存的服务进程号, 如果只是1个服务,默认一般默认为1,最终得到一个createdump.1的文件
/usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.0/createdump 1
如果出现以下信息:
Writing minidump with heap to file /tmp/coredump.1
ptrace(ATTACH, 1) FAILED Operation not permitted
说明没有权限,需要在docker run的时候带上命令 --privileged=true 获取到root权限。

从容器中移出, 并放到自己希望的位置上。
docker cp dockername:/tmp/coredump.1 /home/coredump.1

2. 读取dump文件的三个方式
现在已经有了coredump.1,要想办法读取coredump.1进行下一步的分析。
方案有多种,但是最终都是通过sos命令来查看dump信息。
有以下三条路线:

通过windbg+sos读取
读取dump时需所处环境:windows
这块没有尝试,理论上似乎可以。虽然windbg是只能在windows上运行,但结合sos应该可以在windows中读取dump。

dotnet自带的dotnet-dump进行读取
测试读取dump时需所处环境:linux
这个工具的好处,相比下面lldb+sos的方案,安装方便, 官方文档说明点此。

安装dotnet-dump
dotnet tool install -g dotnet-dump

设置路径, 结合实际dotnet所在目录

export PATH=$PATH:xxx/.dotnet/tools
export DOTNET_ROOT="xxx/dotnet"


载入dump文件
dotnet-dump analyze coredump.1
进入后,执行clrthreads,就会列出当时正在运行的托管线程。

clrthreads
如果无法得到预期结果,出现了:
Failed to load data access module, 0x80004005
Can not load or initialize libmscordaccore.so. The target runtime may not be initialized.
说明必须依赖libmscordaccore.so,但是没有被加载。可惜dotnet-dump工具还不支持单独setclrpath功能,无法载入这个so文件。
通过github看3.1.57502之后的版本应该能支持单独setclrpath了, 因为代码已经改了。

使用lldb+sos读取(推荐)
测试读取dump时需所处环境:Ubuntu
为什么是Ubuntu?因为lldb版本在Ubuntu环境下安装会比较简单。

安装lldb
分析.net core2.1及以上的需要装lldb-3.9,2.1之前的需要装3.6版本了。
apt-get update && apt-get install -y \
    cmake llvm-3.9 \
    clang-3.9 \
    lldb-3.9 \
    liblldb-3.9-dev \
    libunwind8 \
    libunwind8-dev \
    gettext \
    libicu-dev \
    liblttng-ust-dev \
    libcurl4-openssl-dev \
    libssl-dev \
    uuid-dev \
    libnuma-dev \
    libkrb5-dev

安装后通过lldb-3.9命令,能进入就代表正常。

在这里插入图片描述

2. 确认sos插件可以使用:
进入lldb后,输入soshelp,能看到以下信息确认soshelp可以使用:

在这里插入图片描述

如果看不到:
版本是.net core3及之后的新版:退出lldb,安装dotnet-sos后就能显示

版本是.net core3之前的旧版本:在lldb里加载下sos插件,然后再调用下soshelp就能显示了。

plugin load 你的路径/dotnet/shared/Microsoft.NETCore.App/对应版本/libsosplugin.so

都安装完了,带上dump文件测试下
lldb-3.9 $(which dotnet) --core 你的dump文件路径/coredump.1
进入到lldb后
如果是.net core3之前的版本,需要:
plugin load 你的路径/dotnet/shared/Microsoft.NETCore.App/对应版本/libsosplugin.so


查看下当前dump文件里的线程,输入sos Threads后就能看到:

在这里插入图片描述

比如想看ID 11的线程详情,可以先setsostid 14 11锁定线程:在这里插入图片描述
然后再sos ClrStack查看线程内部信息

 在这里插入图片描述


如果sos Threads后无法得到预期结果,出现了:
Failed to load data access module, 0x80004005
Can not load or initialize libmscordaccore.so. The target runtime may not be initialized.
说明必须依赖libmscordaccore.so,执行setclrpath:
setclrpath 你的路径/dotnet/shared/Microsoft.NETCore.App/对应的.net core版本

3.分析
我们已经能通过sos的命令显示出堆栈信息,通过这些信息就可以进行分析。
首先一定要熟悉sos里面的每个命令,因为上面不管哪种读取dump方式,其实最终都是依靠sos插件。
然后根据遇到的不同情况再做不同角度的分析, 这里顺便连接一些通用的分析方法:
内存使用过多的情况分析
CPU过高的情况分析
————————————————
版权声明:本文为CSDN博主「iamfrankjie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/iamfrankjie/article/details/105020929

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐