2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

中小型研发团队架构实践:生产环境诊断利器 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:583485

评论

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

前端食堂技术周刊第 47 期:Docusaurus 2.0 、7 月登陆网络平台的新内容 、Nuxt.js 团队的轮子库

童欧巴

JavaScript 前端

2022秋招前端面试题(十)(附答案)

helloworld1024fd

8月份DB-Engines 数据库排行榜最新战况

雨果

数据库

C++运算符重载(二)之左移运算符重载

CtrlX

c c++ 进阶 重载 8月月更

一文教会你快速上手 Vim

昆吾kw

vim Linux

如何正确理解线程机制中常见的I/O模型,各自主要用来解决什么问题?

PivotalCloud

Linux Linux Kenel

SQL与NoSQL最终会走向融合吗?

雨果

nosql sql

OneFlow源码解析:算子指令在虚拟机中的执行

OneFlow

虚拟机 源码解析 算子

数据库治理利器:动态读写分离

阿里巴巴云原生

数据库 阿里云 微服务 云原生

数据治理(五):元数据管理

Lansonli

大数据 数据治理 8月月更

短视频软件开发——平台同质化如何破局

开源直播系统源码

软件开发 直播源码 短视频直播源码 短视频直播系统源码

GPU加速Pinterest推荐模型,参数量增加100倍,用户活跃度提高16%

OneFlow

机器学习 深度学习 gpu

STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建

DS小龙哥

8月月更

呵呵,JavaScript 真好玩(苦笑脸)

掘金安东尼

JavaScript 前端 8月月更

Gitlab刚发布一项禁止使用 Windows 的公司政策

雨果

gitlab Github'

企业如何判断数据治理是否成功?

雨果

数据治理

50个Java面试必问的面试题,这里都给你整好了

千锋IT教育

中小规模网站架构

舟停江吹雪

Linux

谷歌数据中心发生“电力事故”造成 3 人受伤

雨果

数据中心 谷歌

Gartner再次重申了“数据编织”的重要价值

雨果

数据编织

使用CSS实现多种Noise噪点效果

dragonir

CSS html html5 css3

开源一夏 | mysql5.7安装部署-yum安装

zhangpfly

MySQL 开源 linux运维 #开源 8月月更

一起畅聊「云+操作系统」!龙蜥社区亮相阿里巴巴开源开放周,完整议程来了

OpenAnolis小助手

数据库 操作系统 龙蜥社区 阿里巴巴开源开放周 开源共享

Linux服务器端网络抓包和分析实战

程序员欣宸

Java Linux 8月月更

打工人的第27天-平凡但不平淡的日子

Amazing_eve

#开源

面试突击73:IoC 和 DI 有什么区别?

王磊

Java 常见面试题

是什么影响了MySQL性能?

TimeFriends

8月月更

2022秋招前端面试题(九)(附答案)

helloworld1024fd

学Python爬虫,不看看m3u8文件如何加密?i春秋 m3u8 文件加密解析

梦想橡皮擦

Python 爬虫 8月月更

快速上手,征服三种不同分布式架构调用方案

知识浅谈

分布式 8月月更

JWT 实现登录认证 + Token 自动续期方案

CRMEB

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