.NET 容器环境下创建应用 dump 文件

Intro

有时候我们的应用会出现一些异常的情况,比如内存飙升,线程死锁等等,通过一些 metrics 我们可能大概的了解内存是增长了,但是具体是哪里增长了,单单看内存的变化很难看出来哪里导致的内存变化,所以很多时候我们还是需要对应用进行 dump,通过分析应用 dump 文件来进一步分析是哪里出现的问题。

Prepare

在容器中进行 dump 的时候我们需要 Linux 中的 SYS_PTRACE 权限,所以需要在部署或运行容器的时候指定一下(默认是没有的)

  • 如果你是直接用 docker run 执行的话可以在执行 docker run  的时候指定 docker run --cap-add=SYS_PTRACE

  • 如果你使用 docker compose 来运行,可以在 docker-compose.yml 配置文件中配置 cap_add,下面是一个示例

    version: '2.1'
    services:reservation:build:context: .dockerfile: Dockerfilecontainer_name: reservationcap_add:- SYS_PTRACE
    
  • 如果你在 k8s 中使用,需要在 k8s 的 yaml 文件中配置,示例如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:name: sparktodo-apilabels:app: sparktodo-api
    spec:replicas: 1revisionHistoryLimit: 0template:    spec:containers:- name: sparktodo-apiimage: weihanli/sparktodo-api:latestimagePullPolicy: IfNotPresentresources:requests:memory: "64Mi"cpu: "20m"limits:memory: "128Mi"cpu: "50m"ports:- containerPort: 80
    +         securityContext:
    +           capabilities:
    +             add: ["SYS_PTRACE"]
    

我们也可以在容器中检测是否已经开启了 SYS_PTRACE 权限,可以通过命令 capsh --print 来查看已经配置的权限,如果提示命令不存在,则需要安装一个 package,alpine 安装 libcap,Ubuntu 安装 libcap2-bin

# alpine
apk add libcap# ubuntu
apt-get install libcap2-bin

createdump

createdump 是随着 .NET Core runtime 一起发布的一个创建 dump 的一个工具,createdump 可以收集托管信息和 Native 信息,默认 createdump 会创建一个 mini dump,会创建一个比较小的一个 dump,仅包含一些必要的托管信息和堆栈信息,我们也可以通过参数来控制生成全量的 dump(full dump),全量 dump 生成的 dump 文件会比较大,但是包含的信息会比较多,内存中所有的信息都会包含在内。mini dump 没有 full dump 包含那么多有用的信息,所以大小会比较小,通常你请别人帮忙分析 dump 的时候都是选择 full dump。

createdump 一般位于 /usr/share/dotnet/shared/Microsoft.NETCore.App/<version>/createdump

使用起来直接用 createdump <pid> 就可以了,默认会创建一个 minidump,如果要创建一个 full dump,需要指定参数,createdump <pid> -u 或者 createdump <pid> --full

-f, --name - dump path and file name. The %p, %e, %h %t format characters are supported. The default is '/tmp/coredump.%p'
-n, --normal - create minidump.
-h, --withheap - create minidump with heap (default).
-t, --triage - create triage minidump.
-u, --full - create full core dump.
-d, --diag - enable diagnostic messages.

我们可以使用下面的格式来作为 dump 文件中的占位符:

%%  A single % character.
%d  PID of dumped process (for backwards createdump compatibility).
%p  PID of dumped process.
%e  The process executable filename.
%h  Hostname return by gethostname().
%t  Time of dump, expressed as seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).

dotnet diagnostics tool

微软提供了一系列的 dotnet 诊断工具可以帮助我们诊断应用程序中的问题,

  • dotnet-counters:  一个性能监视工具,用于初级运行状况监视和性能调查

  • dotnet-dump: 可在不使用本机调试器的情况下收集和分析 Windows 和 Linux  的 Core Dump

  • dotnet-gcdump: 可用于为活动 .NET 进程收集 GC dump

  • dotnet-trace: 可以使用来自应用的有意思的分析数据,分析数据通过 .NET Core 中的 EventPipe 公开,这些数据可帮助你分析应用运行缓慢的根本原因。

  • dotnet-stack: 可以快速打印正在运行的 .net 进程中的所有线程的托管堆栈

可以使用安装 global tool 的方式安装,在运行时容器中安装 dotnet tool 可以参考之前一篇文章介绍,借助多阶段构建来方便的安装 dotnet tool,示例 dockerfile 如下:

FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS base
# https://www.abhith.net/blog/docker-sql-error-on-aspnet-core-alpine/
RUN apk add icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
# use forward headers
ENV ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
LABEL Maintainer="WeihanLi"
EXPOSE 80FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build-env
WORKDIR /app# 安装 dotnet tool
RUN dotnet tool install --global dotnet-dump
RUN dotnet tool install --global dotnet-gcdump
RUN dotnet tool install --global dotnet-countersCOPY SparkTodo.Shared/SparkTodo.Shared.csproj SparkTodo.Shared/
COPY SparkTodo.API/SparkTodo.API.csproj SparkTodo.API/
RUN dotnet restore SparkTodo.API/SparkTodo.API.csproj# copy everything and build
COPY . .WORKDIR /app/SparkTodo.API
RUN dotnet publish -c Release -o out# build runtime image
FROM base AS final# 从前面的 SDK 镜像中拷贝 dotnet tools 到 runtime 镜像中
COPY --from=build-env /root/.dotnet/tools /root/.dotnet/tools
# 设置 PATH 以方便使用
ENV PATH="/root/.dotnet/tools:${PATH}"WORKDIR /app
COPY --from=build-env /app/SparkTodo.API/out .
ENTRYPOINT ["dotnet", "SparkTodo.API.dll"]

你也可以按照上面的方式安装自己想要安装的 dotnet tool,按上面安装之后我们就可以直接使用 dotnet-dump/dotnet-gcdump/dotnet-counters 命令了

dump 之旅

container for test

了解一些基础知识之后,我们就来开始创建 dump 吧,示例应用在 Github 上 https://github.com/WeihanLi/SparkTodo,你可以下载这个应用来做尝试,或者在自己的应用上来试验

首先我们 build 一个 docker 镜像,在项目根目录执行 docker build -t sparktodo-api . 来构建镜像

镜像构建好之后,运行一个容器来进行测试

docker run -d --name sparktodo-api --cap-add=SYS_PTRACE sparktodo-api

容器运行成功之后,可以使用下面的命令进入到容器中,出现下图提示则成功的进入容器中了

docker exec -it sparktodo-api sh

Createdump

首先我们来使用自带的 createdump 来创建一个应用的 dump,

有两种方式找到我们的 createdump

我们可以先切换目录到 /usr/share/dotnet/shared/Microsoft.NETCore.App,然后 ls 查看当前的 runtime 版本,切换到版本目录下即可找到 createdump

另外一种方式,我们可以通过 dotnet --info 来查看当前 runtime 版本,然后直接切换到对应的 /usr/share/dotnet/shared/Microsoft.NETCore.App/<dotnet-version> 目录下即可

通常情况下,我们的容器中只有一个进程,进程 Id 为 1的进程通常就是我们的应用进程,如果不确定的话也可以使用 ps -ef 命令来查看当前的进程信息


可以看到,PID 为 1 的进程就是我们的应用所在的进程,然后就可以通过下面的命令来创建 dump 了

./createdump 1 -u

看到这样的提示,我们的 dump 就创建成功了,这样我们可以使用 LLDB 或者 dotnet-dump 进行 dump 分析了

dotnet-dump

dotnet-dump 是微软提供的一个很方便的 dump 分析和收集工具,dotnet-dump 只能分析托管代码,但是绝大部分场景下对我们来说已经足够了,而且 dotnet-dump 是一个 dotnet tool,可以在各个平台下提供完全一致的体验,不像 LLDB 每个系统的安装方式可能都不一样,安装的版本也可能不同,不如 dotnet-dump 体验良好

首先我们可以使用 dotnet-dump ps 来查看可以进行 dump 的 dotnet 进程,然后使用 dotnet-dump collect -p <pid> 来创建 dump 文件


dotnet-gcdump

dotnet-gcdump 也是微软提供的一个用来分析应用程序问题的 dotnet tool,dotnet-dump 创建的 dump 会比较大,包含除了 gc 之外的其他信息,比如 lock 情况,线程堆栈信息等,使用 dotnet-gcdump 创建的 dump 仅包含 gc 堆的信息,dump 文件会小很多,并且 gcdump 文件可以直接用 VS 打开,可以比较方便的查看 GC 内存占用信息,dotnet-gcdump 的使用和 dotnet-dump 类似,并且新版本(.NET 5.0)的 dotnet-gcdump 可以通过 dotnet-gcdump report -p <pid> 直接从某一个进程导出 GC 内存使用信息

通过 dotnet-gcdump collect -p <pid> 来创建 GC dump 文件

More

容器中的 dump 生成之后可以通过 docker cp(k8s 中可以用 kubectl cp)将 dump 文件拷贝到本地来进行分析,新版本的 dump 文件可以直接使用 VS 打开

微软的官方文档真的是一个宝库,有很多很不错的文档,关于 dotnet 诊断工具也有几篇很有用的介绍,没事的时候看看文档,说不定就能发现宝藏~~

References

  • https://docs.microsoft.com/en-us/dotnet/core/diagnostics/debug-linux-dumps

  • https://www.programmersought.com/article/81354675797/#dotnetdotnetdump_45

  • https://man7.org/linux/man-pages/man7/capabilities.7.html

  • https://stackoverflow.com/questions/43621959/how-can-i-find-out-which-capabilities-a-container-has-been-given

  • https://stackoverflow.com/questions/38758627/how-can-we-add-capabilities-to-a-running-docker-container

  • https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

  • https://stackoverflow.com/questions/6903329/minidump-vs-fulldump

  • https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/dotnet-tools.md

  • https://github.com/WeihanLi/SparkTodo

.NET 容器环境下创建应用 dump 文件相关推荐

  1. RAC环境下创建本地数据文件的解决方法

    引用收藏:http://blog.itpub.net/501889/viewspace-1083311/ 同事不小心,在RAC环境下创建了本地数据文件,这个肯定会出问题的,节点2不能访问此数据文件.其 ...

  2. Linux环境下创建运行.java文件

    1.下载安装jdk. 一条yum指令就可以搞定了,也可以自己从windows上共享文件进行操作,有些复杂,这里不做详细描述. 以后熟练了,可能进行二更. yum install java-1.8.0- ...

  3. linux环境生成weblogic密钥,Linux环境下创建weblogic服务.doc

    Linux环境下创建weblogic服务 weblogic用户登录10.218.0.25. 执行一下命令 cd /bea/weblogic92/common/bin ./config.sh 选择创建一 ...

  4. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

  5. ROS 教程之 navigation :在 catkin 环境下创建costmap layer plugin

    在做机器人导航的时候,肯定见到过global_costmap和local_costmap.global_costmap是为了全局路径规划服务的,如从这个房间到那个房间该怎么走.local_costma ...

  6. 容器环境下如何将NuGet包XML文档添加到Swagger

    容器环境下将NuGet包XML文档添加到Swagger 在.NET Core项目开发过程中,为了实现代码复用,我们将可以重复使用的部分拆分成一个个小的NuGet包.这些NuGet包可以在其他系统中复用 ...

  7. 超详细Spring MVC的环境配置:IDEA环境下创建Maven WebAp

    Spring MVC的环境配置: 1. IDEA环境下创建Maven WebApp 配置示例如下: 第一步,创建maven工程 第二步,配置web功能: 第三步,配合Tomcat 运行web文件 2. ...

  8. 嵌入式:Keil uvision5环境下创建一个工程模板(步骤超详细)

    嵌入式:Keil uvision5环境下创建一个工程模板(步骤超详细) 1.创建一个空的文件夹,命名为"test"(可以为任何名字) 2.打开test文件夹,在该目录下依次创建两个 ...

  9. IIS+php环境下:上传文件出现:windows server PHP Warning: mkdir(): Permission denied 解决办法

    PHP Warning: mkdir(): Permission denied:解决办法 最近买个了腾讯云服务器(windows server 2012 r2)配置了个iis+php+mysql的网站 ...

最新文章

  1. 震撼!17 个改变世界的数学公式...
  2. MySql error 1010 无法删除数据库
  3. Groovy 1.5.7 出现java.lang.LinkageError问题
  4. [6]2020-WACV-Adversarial Sampling for Active Learning论文笔记
  5. 谷歌手势插件--crxMouse Chrome™ 手势
  6. 水稻PHP基因,科学网—和驯化相关的水稻基因 - 闫双勇的博文
  7. 强连通分量(Tarjan算法)
  8. Scintilla的高级技法
  9. vue项目pc端页面适配
  10. Leetcode 853 车队
  11. 照着这本“书”,3年量产自动驾驶卡车
  12. 西门子KTP二代精简触摸屏点击无反应,触摸失效的处理对策
  13. VB.NET读取Excel数据在CAD上展图
  14. 利用HbuilderX制作简单网页: HTML5期末大作业——html5漫画风格个人主页
  15. Jina文章转载:多模态AI的范式变革多模态AI总结(2022年COLING会议)
  16. CCS 使用报错合集 -mcu:cc26xx
  17. CUPS之gutenprint生成ppd文件
  18. html相同标签nth,比较CSS3选择器:nth-child和:nth-of-type之间的区别
  19. Flutter syncfusion_flutter_charts 折线图使用心得
  20. keepass密码管理工具的汉化

热门文章

  1. NetBeans 6.5 正式发布
  2. CIO们对数据中心虚拟化心存的六大疑虑
  3. man:命令帮助使用手册
  4. 在程序员的道路上,义无反顾的努力,有思想的人,很多,好的想法,需要学习。(以此共勉)...
  5. C# 图片加水印例程
  6. 如何在Windows 10上使用Microsoft Defender扫描文件或文件夹中的恶意软件
  7. β射线与哪些物质可产生较高的韧致辐射_辐射无所不在,香蕉土豆里都有?我们还能愉快生活吗?...
  8. 【本人秃顶程序员】技巧分享丨spring的RestTemplate的妙用,你知道吗?
  9. 高清、免版权美图资源大全
  10. 负载均衡环境搭建实战之nginx和tomcat