.Net Core在Linux环境dump分析

前言

在本地开发调试的时候,基于VS的工具能方便看出内存泄露的信息:
在这里插入图片描述

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

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

1. 生成dump文件

生成dump文件,依赖createdump工具,这个工具是.net core runtime自带的,所以只要运行在.net core上的项目, 就可以直接使用该工具。

  1. 进行容器内部,dockername 可以通过docker ps得到
docker exec -it dockername /bin/bash
  1. 找到工具对应的目录:
find /usr/share -name createdump

在这里插入图片描述

  1. 通过上面的路径执行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权限。

  1. 从容器中移出, 并放到自己希望的位置上。
docker cp dockername:/tmp/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的方案,安装方便, 官方文档说明点此

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

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

export PATH=$PATH:xxx/.dotnet/tools
export DOTNET_ROOT="xxx/dotnet"
  1. 载入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环境下安装会比较简单。

  1. 安装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
  1. 都安装完了,带上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过高的情况分析

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值