IIS 占用 CPU %问题排查方案

有时候辛辛苦苦写个网站,挂到服务器上一看,CPU给百分百了,这种问题百分之八九十都是因为代码写有问题,而不是因为系统设置的问题,这种问题也比较难排查。但是结合一些工具也可以找到原因的,关于windbg的使用,好像有本关于.net调试的书,大家有兴趣可以看看,网上也有一些帖子,但关于ANTS Profiler的帖子就比较少了,大家也可以下载试用版来帮助解决问题

1 准备日志
1.1 用perfmon添加计数器日志,添加如下计数器

ASP.NET:所有计数器
Memory:所有计数器
Process:所有计数器和所有实例
Processor:所有计数器和所有实例
Thread:所有计数器和所有实例
Web service:所有计数器和所有实例

1.2 间隔改成1,单位改成秒

1.3 用鼠标右键单击这个日志名,然后单击开始。确保日志捕获了处理器利用率猛增至 100% 的那段时间内的所有数据。

2  抓Dump
2.1 用IIS Diagnostics Toolkit工具找出占用CPU高的w3wp进程ID

2.2 用windbg执行以下命令adplus –hang –p pid并抓取dump

3 检查日志
3.1 识别哪一个进程消耗了大部分的 CPU 时间

用perfmon打开准备好的日志文件,用鼠标右键单击图表,然后单击添加计数器。在添加计数器对话框中,从性能对象列表中选择 Process。选择从列表中选择计数器,然后从此列表框中选择 %Processor Time。选择所有实例,单击添加,然后单击关闭。

这将为我们提供所有处理器及其 CPU 使用情况的列表。现在您需要查清哪个进程引起了 100% 的 CPU 问题。

确保选中了突出显示工具按钮(黄色灯泡图标)。现在您可以滚动这些计数器,将除最接近 100% 标记的那个进程之外的所有进程全部删除。确保只选择了那些与您有关系的计数器。例如,如果您正在调试 100% 的 CPU 利用率的问题,您也许应该查找w3wp、inetinfo、其它的脱机处理的 COM 程序包/应用程序 (MTX.EXE/DLLHOST.EXE) 或者 IIS 应用程序。

3.2 找出该进程内部的那些在出现 100% 的 CPU 问题时仍然活动的线程实例

一旦您在进程级将问题隔离出来,您就可以将注意力集中在该进程内部的那些在出现 100% 的 CPU 问题时仍然活动的线程上,并试着隔离引起问题的那个线程。为此,我们添加更多的计数器来显示该进程中所有线程的 CPU 使用情况。对于本例而言,就是为w3wp进程(假设它占用CPU最高)中的所有线程添加计数器。用鼠标右键单击图表,然后单击添加计数器。在添加计数器对话框中,从性能呢个对象列表中选择 Thread。选择从列表中选择计数器,然后从列表框中选择 %Processor Time。选择 从列表中选择实例,然后选择以 w3wp/* 开头的所有实例。单击添加,然后单击关闭。

这时,图表中显示在w3wp进程中的所有线程的 CPU 使用情况。

现在可以滚动计数器,将除最接近 100% 标记的那个线程以外的所有线程全部删除。这样我们就准确地找到了引起问题的那个线程(假设它的线程实例ID为12)。

3.3 找出导致CPU占用100%的线程ID

我们只保留实例ID 为12的线程(上一步操作留下的那个线程),它占用了最长的 CPU 时间。现在必须找出这个线程的线程 ID,然后在 WinDBG 中找到这个线程并对它进行调试。

要找出线程 ID,请用鼠标右键单击图表,然后单击添加计数器。在添加计数器对话框中,从心能对象列表中选择 Thread。选择从列表中选择计数器,然后从此列表框中选择 ID Thread。选择从列表中选择实例,然后选择实例w3wp/12(看具体情况而定)。单击添加,然后单击关闭。

这样我们就得到了引起问题的那个线程的 ID。选择 ID Thread 计数器。记录该计数器的最后一个值、最大值、最小值和平均值。通常这四个数是相同的。记录这个值(比如说1460),并切换到 WinDBG 应用程序。

4  找出导致CPU占用100%的相关代码
4.1 打开windbg,点击菜单File/Open Crash Dump,选择第二步用Adplus抓的dump文件

在 WinDBG 的 View 菜单上,单击 Processes and Threads。这将显示在出现 100% 的 CPU 问题时在w3wp进程内部运行的线程的一个列表。查找您在性能监视器中记录的线程 ID 号(3.3步中找到的线程ID,这个ID是十进制的,用calc换算成16进制标识)。如果在列表中找到此 ID 号(16进制),则单击选中它。单击 OK。

在 View 菜单上,单击 Call Stack。这时显示引起问题的那个线程的堆栈。该堆栈将有问题的方法隔离出来。一旦我们找到这个方法,我们就可以返回原代码,查看是哪行代码引起这个问题的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注