速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

中小型研发团队架构实践:生产环境诊断利器 WinDbg 帮你快速分析异常情况 Dump 文件

  • 2018-01-15
  • 本文字数:4525 字

    阅读完需:约 15 分钟

一、简介

生产环境偶尔会出现一些异常问题,WinDbg 或 GDB 就是解决此类问题的利器。调试工具 WinDbg 如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具,Dump 文件类似于飞机的黑匣子,记录着生产环境程序运行的状态。

本文主要介绍了调试工具 WinDbg 和抓包工具 ProcDump 的使用,并分享一个真实的案例。N 年前不知谁写的代码,导致每一两个月偶尔出现 CPU 飙高的现象。我们先使用 ProcDump 在生产环境中抓取异常进程的 Dump 文件,然后在不了解代码的情况下通过 WinDbg 命令进行分析,最终定位到有问题的那行代码。

1、WinDbg

WinDbg 是在 Windows 平台下的、强大的用户态和内核态调试工具。相比较于 Visual Studio,它是一个轻量级的调试工具,所谓轻量级指的是它的安装文件大小较小,但是其调试功能,却比 VS 更为强大。

它的另外一个用途是可以用来分析 Dump 数据。WinDbg 是 Microsoft 公司免费调试器调试集合中的 GUI 的调试器,支持 Source 和 Assembly 两种模式的调试。

WinDbg 不仅可以调试应用程序,还可以进行 Kernel Debug。结合 Microsoft 的 Symbol Server,可以获取系统符号文件,便于应用程序和内核的调试。

WinDbg 支持的平台包括 x86、IA64、AMD64。虽然 WinDbg 也提供图形界面操作,但它最强大的地方还是有着强大的调试命令,一般情况会结合 GUI 和命令行进行操作,常用的视图有:局部变量、全局变量、调用栈、线程、命令、寄存器、白板等。其中“命令”视图是默认打开的。

2、DebugDiag

DebugDiag 最初是为了帮助分析 IIS 的性能问题而开发的,它同样可以用于任何其他的进程。DebugDiag 工具主要用于帮助解决如挂起、 速度慢、 内存泄漏或内存碎片,和任何用户模式进程崩溃等问题。

该工具包括附加调试脚本,侧重于互联网信息服务(IIS)应用程序、 Web 数据访问组件、 COM+ 和相关 Microsoft 技术、SharePoint 和.NET。它提供可扩展对象模型中的 COM 对象的形式,并具有一个内置的报告框架提供的脚本主机。它由 3 部分组成,包括调试服务、 调试器主机和用户界面。

3、ProcDump

ProcDump 是 System Internal 提供的一个专门用来监测程序 CPU 高使用率从而生成进程 Dump 文件的工具。ProcDump 可以根据系统的 CPU 使用率或者指定的性能计数器来针对特定进程生成一系列的 Dump 文件,以便调试者对事故原因进行分析。

二、工具下载地址

复制代码
1、WinDbg 下载
   x86 位版本下载:http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup/WinSDKDebuggingTools/dbg_x86.msi
   x64 位版本下载:http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/setup/WinSDKDebuggingTools_amd64/dbg_amd64.msi
2、DebugDiag v2 Update 2 下载:https://www.microsoft.com/en-us/download/details.aspx?id=49924
3、ProcDump v9.0 下载:https://download.sysinternals.com/files/Procdump.zip

三、获取异常进程的 Dump 文件

有以下四种方式获取 Dump 文件,具体如下:

1、通过【任务管理器】获取 Dump 文件,这样获取的是 MinDump

2、利用 WinDbg 的 adplus 获取 Dump 文件,这样获取的是 FullDump

3、通过 DebugDiag 创建.NET 异常转储 Dump 文件

4、通过 ProcDump 抓取异常线程 Dump 文件。

现在重点介绍通过 ProcDump 抓取异常线程 Dump 文件,使用方法如下:

4.1、命令行

复制代码
procdump [-a] [[-c|-cl CPU usage] [-u] [-s seconds]] [-n exceeds]
[-e [1 [-b]] [-f <filter,...>] [-g] [-h] [-l] [-m|-ml commit usage]
[-ma | -mp] [-o] [-p|-pl counter threshold] [-r] [-t]
[-d <callback DLL>] [-64] <[-w] <process name or service name or PID>
[dump file] | -i <dump file> | -u | -x <dump file> <image file>
[arguments] >] [-? [ -e]]

实例:

复制代码
procdump -c 70 -s 5 -ma -n 3 w3wp
 - 当系统 CPU 使用率持续 5 秒超过 70% 时,连续抓 3 个 Full Dump。
procdump outlook -p "\Processor(_Total)\% Processor Time" 80
 - 当系统 CPU 使用率超过 80%,抓取 Outlook 进程的 Mini Dump。
procdump -ma outlook -p "\Process(Outlook)\Handle Count" 10000
 - 当 Outlook 进程 Handle 数超过 10000 时抓取 Full Dump
procdump -ma 4572
 - 直接生成进程号位 4572 的 Full Dump。

下图是在 WindgbHighCpu 进程中造成 High CPU 时运行 ProcDump 命令的运行效果,可以看到在 CPU 每次持续 5 秒达到 5% 后就会生成相应的 Dump 文件,共生成了 3 份 Full Dump 文件:

注意:

  • ProcDump 需要进程已经启动,并且中途不能停止。比如需要抓取 IIS Worker Process 的 High CPU Dump,由于 IIS Worker Process 默认会配置 Idle Timeout = 20 min,即该进程在 20 分钟内没有任何请求的话就会自动结束,这种情况下 ProcDump 也会自动结束。需要重新运行命令。因此如果目标程序存在这样的配置,需要暂时将该配置取消。
  • 有些系统管理员希望能够运行该工具后退出用户 session,ProcDump 是做不到的,如果有这种需求可以考虑使用 DebugDiag。
  • 在调试 High CPU 问题的时候经常用到的一个命令是!runaway,但是有些时候!runway 在 ProcDump 抓取 Dump 文件的过程中运行不出来,报错信息如下:

0:000> !runaway ERROR: !runaway: extension exception 0x80004002. "Unable to get thread times - dumps may not have time information"解决方法是将 Debugging Tools for Windows (WinDbg) 安装目录下的 dbghelp.dll 拷贝到 procdump.exe 所在目录下,然后再运行命令抓取 Dump。

四、WinDbg 使用方法

操作步骤如下:

1、抓取异常程序的 Dump 文件。

2、设置符号表

符号表是 WinDbg 关键的“数据库”,如果没有它,WinDbg 基本上就是个废物,无法分析更多问题。所以使用 WinDbg 设置符号表,是必须要走的一步。

  • a、运行 WinDbg 软件,然后按【Ctrl+S】弹出符号表设置窗。
  • b、将符号表地址:SRV*C:\Symbols*
    http://msdl.microsoft.com/download/symbols
    粘贴在输入框中,点击确定即可。点击确定之前,请先确认红色字的文件夹是否已被新建。

注:红色字表示符号表本地存储路径,建议固定路径,可避免符号表重复下载。

3、学会打开第一个 Dump 文件!

使用【Ctrl+D】快捷键,或者点击 WinDbg 界面上的【File=>Open Crash Dump…】按钮,来打开一个 Dump 文件。

当你想打开第二个 Dump 文件时,可能因为上一个分析记录未清除,导致无法直接分析 Dump 文件,此时你可以使用快捷键【Shift+F5】来关闭上一个对 Dump 文件的分析记录。

4、通过简单的几个命令学会分析 Dump 文件

分享一个数据库连接超时的 Dump 案例的分析过程:

当你打开一个 Dump 文件后,可能因为太多信息,让你无所适从,不过没关系,我们只需要关注几个关键信息就可以了。

a. 加载 SOS 扩展命令

加载 SOS 之前,先确定 SOS 的位置和版本,确定方法如下:

如果安装了 Visual Studio,那么先按照如下步骤打开 VS 的命令行:

然后,在打开的 VS 命令行中输入 where sos.dll,使获得 SOS 的位置和版本:

确定完 SOS 位置和版本号后,开始加载 SOS 扩展命令:

.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll如下图所示:

b. 使用!clrstack 命令来查看当前的调用堆栈信息

如下图所示:

c. 使用!dso 命令来查看堆栈上的所有对象详细信息

如下图所示:

综合以上分析可以大胆地猜测 Common.cs 中第 16 行“ Data Source=***;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***”的这个数据库连接字符串应该有问题,然后到代码中相应的地方进一步确认和修改就可以了。

五、真实案例

分享一个笔者工作过的公司的某业务系统使 CPU 飙高 90% 或以上的 Dump 案例的分析过程,步骤如下:

1、使用 ProcDump 抓包

2、加载 SOS 扩展命令:

.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

3、分析:

执行!runaway 命令,查看线程使用 CPU 时间情况,如下图所示。着重分析前面几个线程。

执行~22s 命令,进入到线程 22,如下图所示:

执行!clrstack 命令查看当前线程堆栈变量值的信息,从图中可以猜出大概是 ExecuteNonQuery() 这方法有点问题,如下图所示:

再执行!dso 命令可以查看堆栈上的所有对象详细信息,如下图所示:

从图中看,造成 CPU 飙高的罪魁祸首多半由 SQL Server 执行

INSERT INTO [dbo].[tbl_Interface_ProcessLog] (IKey,Username,ClientIP,Module,OrderNo,LogType,Content) VALUES (@IKey,@Username,@ClientIP,@Module,@OrderNo,@LogType,@Content)这条语句时产生异常引起,然后到源代码中找出相应的语句,经过进一步的确认、修改和重新发布后就解决了 CPU 飙高的问题。

至此,掌握几个简单的 WinDbg 命令之后,基本上绝大多数 Dump 大家都可以独立分析了。当然 WinDbg 是个强大的工具,同时产生 CPU 飙高和内存泄漏的原因也有很多。如果想分析得足够准确,那么就只有多学多练,多去分析。因为掌握 WinDbg 分析除了需要懂得几个命令之外,经验更加重要,最后再补充两点:

  • WinDbg 不是专门用于调试.NET 程序的工具,它更偏向于底层,可用于内核和驱动调试,特别是对于某些相当疑难的问题调试有所帮助,例如内存泄漏等问题。进行普通的.NET 程序调试还是使用微软专为.NET 开发所提供的调试工具更方便一些。
  • SOS 扩展命令中最有用的命令是!help,使用该命令可以列出所有可用的 SOS 扩展命令列表,使用!help [SOSCommandName] 可以查看每一个具体扩展命令的详细使用说明。例如!help dumpheap 就可以查看!dumpheap 这个扩展命令的具体使用方法。多多利用!help 命令可以很快上手 SOS。

六、Demo 下载及更多资料

本系列文章涉及内容清单如下(并不按这顺序发布),其中有感兴趣的,欢迎关注:

作者介绍

许珍珠,先后就职于携程网络及古大集团从事架构设计与研发管理工作。具有丰富的互联网技术架构经验与技术管理经验,擅长敏捷开发模式,推崇轻量级的系统架构,对微服务架构有自己独到的见解。目前就职于同程旅游网络,现任交通孵化中心上海创新研发技术负责人,负责整个有票儿 APP 项目架构设计及研发管理工作。

张辉清,10 多年的 IT 老兵,先后担任携程架构师、古大集团首席架构、中青易游 CTO 等职务,主导过两家公司的技术架构升级改造工作。现关注架构与工程效率,技术与业务的匹配与融合,技术价值与创新。

感谢雨多田光对本文的审校。

2018-01-15 16:583170

评论

发布
暂无评论
发现更多内容

全球增长最快的对象存储开源系统MinIO

liuzhen007

8月日更

在线年龄计算器

入门小站

工具

Vue进阶(二十七):Vuex 之 getters, mapGetters, ...mapGetters详解

No Silver Bullet

Vue vuex 8月日更

Android开发:引入重复包报错Error:Execution failed for task ‘:app:transform...’解决方法

三掌柜

8月日更 8月

JavaScript Array 方法详解

程序员海军

JavaScript 方法 大前端 array 引航计划

【Flutter 专题】70 图解自定义 ACEStepper 步进器

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 8月日更

金融级IT架构:网商银行是如何进行数字化落地的

博文视点Broadview

从0开始的TypeScriptの五:webpack打包typescript

空城机

JavaScript typescript 大前端 8月日更

一文带你了解 TreeMap ,LinkedHashMap 的主要特点

4ye

Java 后端 hashmap LinkedHashMap 8月日更

Django 做个小后台,细节在完善一点点,滚雪球学 Python 第三阶段

梦想橡皮擦

8月日更

Rust从0到1-模式-相关语法

rust 语法 模式 Patterns Syntax

Go语言那些事儿之管道的关闭

Regan Yue

Go 语言 8月日更 管道

失败的小项目-外卖cps

箭上有毒

8月日更

【LeetCode】从上到下打印二叉树Java题解

Albert

算法 LeetCode 8月日更

LeetCode题解:781. 森林中的兔子,贪心,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

如果面试官问你 JVM,额外回答逃逸分析技术会让你加分!

陈皮的JavaLib

Java 面试 JVM 逃逸分析 8月日更

在openEuler上做开发?这个大赛拿出30万寻找开源的yyds

华为云开发者联盟

开源 操作系统 服务器 openEuler 鲲鹏

Mybatis自定义拦截器与插件开发

码农参上

8月日更

Prometheus监控的4个黄金指标

Rubble

Prometheus 8月日更

Hive企业级性能优化

五分钟学大数据

hive hive性能优化

【Vue2.x 源码学习】第三十三篇 - diff算法-收尾+阶段性总结

Brave

源码 vue2 8月日更

Linux之netstat命令

入门小站

Linux

命令行操作Java程序的那些事~

Bob

Java 命令行 8月日更

netty系列之:自动重连

程序那些事

Java Netty 程序那些事 响应式系统

small-spring 代码贡献者3个月,敢说精通Spring了,分享我的总结!

小傅哥

spring 小傅哥 cglib aware BeanPost

这几个棘手的面试常见问题,如何高情商的回答?

架构精进之路

情商 8月日更

送你两个神器,关系数据库数据入湖轻松应对

华为云开发者联盟

数据库 数据湖 数据迁移 关系数据库 实时数据

Android开发:获取安卓App版本号的方法步骤

三掌柜

8月日更

手撸二叉树之将有序数组转换为二叉搜索树

HelloWorld杰少

数据结构与算法 8月日更

oeasy教您玩转vim - 14 - # 行头行尾

o

七夕赶上服务器架构升级,女朋友的约会怎么办

华为云开发者联盟

华为云 FunctionGraph DevStar Serverless架构 服务器架构

中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件_架构_张辉清_InfoQ精选文章