IIS 6 + ASP.NET Web 服务-DW20 和 stackoverflow 异常

IIS 6 + ASP.NET Web 服务-DW20 和 stackoverflow 异常

考虑一个 ASP.NET SOAP Web 服务,它启动正常,但在第一次受到攻击时却出现严重故障。

请注意,此部署在测试环境中有效,但在 PreProd 环境中无效。两者都是 Windows 2003 SP3 + IIS 6 + ASP.NET 3.5。全部为最新版本。

我们看到的行为是:

  • 重新启动站点和应用程序池
  • 应用程序池配置为在网络服务下运行。
  • 浏览 .asmx 和 .wsdl 响应正常,正如预期。
  • 向 Web 服务发送格式正确的普通 SOAP 请求/普通负载
  • CPU 使用率 100%
  • 5 秒后,页面请求/站点返回“服务不可用”
  • IIS 日志文件中未创建任何条目(即 c:\windows\system32\logfiles\W3C-foo)
  • 应用程序池最终被停止

严重占用 CPU 的进程是dw20.exe。我不确定为什么 Dr Watson 会参与其中。

事件日志显示 ASP.NET 运行时错误: 替代文本

任务管理器

替代文本

事件日志文本

替代文本

事件类型 clr20r3,P1 w3wp.exe,P2 6.0.3790.3959,P3 45d6968e,P4 错误管理,P5 1.0.0.0,P6 4b86a13f,P7 24,P8 0,P9 system.stackoverflowexception,P10 NIL。

问题

您对这个 system.stackoverflow 异常可能是什么有什么想法?鉴于不同环境之间的代码相同,这可能是有效负载问题吗?可能是配置问题吗?您可以在异常消息中看到我的 .NET 程序集的名称:“ErrorManagement”

答案1

解决这个(可能是独特的)问题的方法:

  • 删除并重新创建所有应用程序池(这可能是过度的和不必要的)
  • 删除磁盘上的应用程序文件
  • 重新部署并新建应用程序版本
  • 确保所有引用都包含在 bin 目录中

答案2

Stackoverflow 异常是一种特殊情况,因为受影响的应用程序无法再执行任何操作(例如记录堆栈跟踪)——在这种情况下,应用程序池进程(w3p.exe)被操作系统终止。这就是 Dr. Watson/DW20 参与其中的原因。您可以尝试使用带有 SOS 扩展的 WinDbg 调试 DW20 保存的转储(如果您不熟悉该工具集,则需要经历一段陡峭的学习曲线——我希望 VS2010 能像承诺的那样让这个过程变得更容易)。

高 CPU 使用率(通常还有高内存使用率)是由 DW20 引起的,如果“崩溃和重启循环”比 DW20 更快并且因此积累了多个 DW20 进程,则这种情况尤其令人讨厌。

IIS 应用程序池的默认设置是在短时间内重新启动崩溃的应用程序不超过 3 次,否则它们将被停止,以保护服务器免受 DoS 攻击。

关于根本原因,stackoverflow:可能是一切......但是这个大胆的猜测怎么样:由于配置错误导致数据库访问失败,生成异常,并且您的应用程序正在将异常记录到数据库,而没有在异常处理中捕获异常;)

答案3

我遇到了这个问题,发现我有一个 LINQ 语句试图删除一些行。它每天都会失败,所以行数一直在增加。异常实际上已被处理并记录到我制作的表中,所以我在那里找到了它。找到了问题表,它有 700k+ 的超重行。我的 LINQ 看起来像这样:

var db = new DatabaseDataContext();
        var updateQueueLogs = db.UpdateQueueLogs;

        List<UpdateQueueLog> listToDelete;

        using (new TransactionScope(
            TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
        {
            listToDelete = (from updateQueueLog
                              in db.UpdateQueueLogs
                            where updateQueueLog.CreatedAt < DateTime.Now.AddDays(-7)
                            select updateQueueLog).ToList();
        }

        updateQueueLogs.DeleteAllOnSubmit(listToDelete);

        db.SubmitChanges();

因此,它提取了完整的对象并获取了 OutofMemory 异常。我将此代码更改为存储过程:

delete from UpdateQueueLogs
 where CreatedAt < DATEADD(day,-7,getdate())

我只是想发布这个,因为如果您没有看到异常,您可能需要检查一些 SQL 表行数,看看是否存在一些超时的 LINQ 语句。

答案4

检查事件查看器中的错误(通常是应用程序日志)。它位于管理工具下。

此外,@markus 的观点很好,IIS 具有相当严格的默认“每 Y 次不超过 X 个线程崩溃”设置,因此如果您访问页面几次并出现此类错误,整个应用程序池都会被关闭。再次检查事件查看器。

相关内容