65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用内存转储文件排查 ASP.NET 应用程序挂起问题

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (4投票s)

2012年5月14日

CPOL

6分钟阅读

viewsIcon

59949

在本文中,我将演示如何使用内存转储文件来排查 ASP.NET 应用程序挂起问题。

引言

一台生产环境的 IIS 服务器每天都会报告出现挂起。我们尝试了所有可能的方法来寻找解决方案,但都无济于事。幸运的是,通过内存转储文件,我们发现了一些线索,最终 pinpoint 了问题的根源。在这里,我将分享我在捕获和分析内存转储文件过程中获得的所有信息和经验。

环境

这是一个基于 ASP.NET 2.0 的 Web 应用程序,运行在 Windows 2008 服务器上,并使用 SQL Server 2008 作为数据库。该 Web 应用程序大量处理文档。所有文档都存储在一个专用的文档服务器上。所有服务器都是基于 VMWare 的虚拟服务器。

问题

在过去的几个月里,我们的客户开始偶尔遇到服务器挂起的情况。当服务器挂起时,没有人可以使用 Web 应用程序,系统管理员也无法远程连接到服务器。起初,我们检查了服务器配置、安装的软件、正在运行的进程、应用程序源代码、事件查看器、IIS 日志等,试图找到一些线索。不幸的是,没有发现任何异常。因此,我们开始专注于寻找一种方法,在 IIS 挂起发生时收集更多信息。这个想法是在服务器挂起时捕获 IIS 内存转储,并使用内存转储工具来了解那一刻发生了什么。

工具

为了在服务器挂起时获取内存转储,我们需要以下工具。

Windows 调试工具

可以在 Microsoft 的“下载和安装 Windows 调试工具”页面 (http://msdn.microsoft.com/en-us/windows/hardware/gg463009) 上获取 Windows 调试工具。Windows 8 Consumer Preview 的 Windows Software Development Kit (SDK) 包含了最新的 Windows 调试工具。

安装完 Windows 8 Consumer Preview 的 Windows Software Development Kit 后,您会在 C:\Program Files(或 64 位 Windows 中的 C:\Program Files (x86))下找到一个 Windows Kits 文件夹。请不要将其与可能已经存在于您 C:\Program Files(或 64 位 Windows 中的 C:\Program Files (x86))下的 Windows SDK 文件夹混淆。Windows Kits 中有很多工具。我们将要使用的是:

  1. cdb.exe
    一个具有控制台界面的用户模式调试器。稍后将在内存转储捕获脚本中使用。
  2. windbg.exe
    一个具有图形界面的用户模式和内核模式调试器。将用于分析捕获的内存转储。

Debug Diagnostic Tool v1.2 (调试诊断工具 v1.2)

Debug Diagnostic Tool (DebugDiag) 旨在协助排查挂起、性能缓慢、内存泄漏或内存碎片以及任何用户模式进程崩溃等问题。该工具包含专注于 Internet Information Services (IIS) 应用程序、Web 数据访问组件、COM+ 和 COM+ 相关 Microsoft 技术、SharePoint 和 .NET Framework 的附加调试脚本。我们真正需要 Debug Diagnostic Tool 的是其用于 windbg 的调试扩展。

如何设置服务器挂起内存转储捕获

我们的客户的服务器是 Windows Server 2008,自带 IIS 7。按照以下步骤设置一个触发器,在 IIS 挂起时生成内存转储。

1. 创建 GenerateDump.bat 批处理文件

批处理文件包含以下脚本:

@if "%_echo%"=="" echo off
setlocal
    set TIMESTAMP=%DATE:~-9%_%TIME%
set TIMESTAMP=%TIMESTAMP:/=_%
set TIMESTAMP=%TIMESTAMP::=_%
set TIMESTAMP=%TIMESTAMP:.=_%
set TIMESTAMP=%TIMESTAMP: =_%
set FILENAME=c:\crash_PID_%1_%TIMESTAMP%.dmp
set LOG=c:\log.txt
set COMMAND= C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\cdb.exe 
             -c ".dump /o /ma %FILENAME%;q" -p %1

echo %COMMAND% > %LOG%
%COMMAND%

endlocal

2. 配置孤立工作进程设置

  1. 在命令窗口中,转到 inetpubadminscripts 文件夹。
    cd c:\inetpub\adminscripts
  2. 要启用孤立工作进程功能,请在命令提示符下键入以下命令:
    adutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanWorkerProcess TRUE
  3. 在命令提示符下,将第 1 步中的批处理脚本设置为在计划回收进程时运行。
    adsutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanActionExe “c:\GenerateDump.bat”
    
    adsutil.vbs SET W3SVC/AppPools/DefaultAppPool/OrphanActionParams “%1%”

    注意:请确保 OrphanActionExe 选项指向上面创建的批处理文件的位置,并确保 w3wp.exe 进程的帐户对此文件具有读取和执行权限。

如何分析内存转储

在 IIS 挂起期间捕获到转储文件后,我们使用 windbg 打开该转储文件。

在 windbg 中加载内存转储

  1. 打开 windbg

    有 x86 版本的 windbg 和 x64 版本的 windbg。运行哪个版本不取决于您的开发机器的 Windows 版本,而是取决于您的内存转储机器的 Windows 版本。基于您运行的 windbg 的版本,您需要在以下步骤中加载相应的调试扩展。

  2. 转到 文件 -> 打开崩溃转储。选择由您的 IIS 服务器捕获的转储文件。

  3. 运行命令
    !symfix

    此命令将自动将符号路径设置为 Microsoft 的符号存储。执行此操作时,您必须有 Internet 连接。或者,您可以提前将符号下载到本地,或者直接指向 Microsoft 的符号服务器,语法如下:

    srv*c:\symbols*http://msdl.microsoft.com/download/symbols

加载额外的调试扩展

windbg 的内置命令对于托管内存转储的分析功能有限,因此您需要一些调试扩展来帮助揭示托管内存转储内部的更多信息。

  1. 运行命令
    !load psscor2

    Psscor2 是 Debug Diagnostic Tool 的一部分。它是一个托管的 windbg 调试扩展。它旨在调试 ASP.NET 2.0 和 3.5 的内存转储。如果您想调试 ASP.NET 4.0 应用程序的内存转储,也可以将 Psscor4 加载到 windbg 中。Psscor2 是调试扩展 sos 的超集。通过将此调试扩展加载到 windbg 中,我们就不再需要 sos 调试扩展了。
    如果您加载 psscor2 失败,因为它找不到正确版本的 mscordacwks,那么您可以使用...

    .cordll –ve –u –I mscorwks –l 

    ...来加载正确的版本。cordll 命令将尝试从几个不同的位置查找正确的 mscorwks,并告诉您这些尝试是否成功。

  2. 运行命令
    !load IISInfo

    IISInfo 调试扩展也是 Debug Diagnostic Tool 的一部分。它用于显示内存转储中的 IIS 和 ASP 信息。

使用调试命令分析内存转储

  1. 运行命令
    .time

    这是一个 windbg 内置命令。用于显示系统正常运行时间、进程正常运行时间、内核时间以及用户时间。

  2. 运行命令
    !aspxpages

    这是来自 psscor2 调试扩展的命令。用于列出哪些 ASP.NET 页面正在哪些线程上处理。

  3. 运行命令
    !Threads 

    这是来自 psscor2 调试扩展的命令。用于列出内存转储中所有正在运行的线程。

  4. 运行命令
    ~[Thread Id]s

    这是来自 psscor2 调试扩展的命令。用于选择特定线程。

  5. 运行命令
    !CLRStack –p
    

    这是来自 psscor2 调试扩展的命令。用于显示当前选定线程的 CLR 堆栈跟踪及参数信息。

  6. 运行命令
    !do [memory address]

    这是来自 psscor2 调试扩展的命令。用于显示指定内存地址中的内容。

  7. 运行命令
    !dae

    这是来自 psscor2 调试扩展的命令。用于转储内存转储中找到的所有 .NET 异常。

  8. 运行命令
    !threadpool

    这是来自 psscor2 调试扩展的命令。用于精确找出转储被捕获时 CPU 的使用情况。我们还将获得一些有用的信息,例如队列中的工作请求数量、完成端口线程和计时器。

  9. 运行命令
    !clientconns

    这是来自 IISInfo 调试扩展的命令。用于查看所有客户端连接。

发现

通过内存转储,我们发现一个长时间运行的进程试图从客户的文档服务器获取文档,但是,由于文档服务器没有及时响应请求,ASP.NET 进程就一直在等待。这种文档请求不断涌入,最终,所有挂起的文档请求处理耗尽了 IIS 服务器。

摘要

Windows 调试工具是在 Windows 中处理复杂应用程序问题的一个非常有用的工具。对我来说,IIS 挂起是一个应用程序开发人员很奇怪的问题。通过内存转储和内存转储分析工具,我们可以收集更多信息并 pinpoint 问题。

© . All rights reserved.