ASP.NET Web 应用程序在部署后不卸载 AppDomains

Posted

技术标签:

【中文标题】ASP.NET Web 应用程序在部署后不卸载 AppDomains【英文标题】:ASP.NET Web application doesn't unload AppDomains after deploy 【发布时间】:2014-08-29 14:16:33 【问题描述】:

当我们部署我们的 Web 应用程序时,我们将所有代码复制到一个新目录,然后将 iis 指向该新目录。当我们这样做时,appdomains 的数量会增加,但不会减少。此外,我们的 Application_End 事件似乎永远不会触发。

在一段未知的时间里,虽然 perfmon 仍然报告了两组 AppDomain,但系统性能非常差,而 GC 时间百分比飙升至 100%。最终我回收了应用程序池,让应用程序再次顺利运行。

额外信息:列出 appdomains 在我的开发机器上显示 2,但 4 在实时服务器上运行...我们只有一个应用程序在池中运行,所以这意味着我们正在使用的某个库是创建应用程序域。

我应该怎么做才能尝试调试正在发生的事情?什么会阻止应用域卸载?

2014 年 9 月 3 日更新

在获得一些更详细的日志信息后,看起来问题不是旧的应用程序域存在,而是在重新启动期间创建的新应用程序域。它不是启动一个新实例,而是启动两个应用程序。有时我们会从旧实例中获取 application_end,有时我们不会。

2014 年 9 月 4 日更新

这两件事都在发生。使用进程资源管理器,我可以在其中一台机器上看到旧的应用程序域仍然存在并且新的应用程序域已经启动。在另一台机器上,只有 2 个应用程序域,但它们的顺序 ID 存在差距。因此启动了两个实例(我们还从应用程序启动中收到了一条日志消息),其中一个实例几乎立即死亡,留下了 2 个应用程序域。

【问题讨论】:

您是否有机会使用 ASP.NET 缓存和一个在缓存过期时重新加载缓存的驱逐方案? 我们确实使用 ASP.NET 应用程序缓存。我们根据用户会话超时插入具有滚动到期的内容。但它不会自行重新加载任何内容。 “滚动到期”是什么意思?你的意思是更新过期时间?我要问的是当对象过期时是否根据缓存管理器的回调重新加载缓存 如果在 x 分钟内未触及缓存键,则从缓存中删除该项目。缓存管理器不会将项目重新加载到缓存中。这些项目只会由发出请求的用户放回缓存中。 【参考方案1】:

虽然我不确定这是应用程序没有卸载应用程序域的唯一原因,但这肯定是一个原因。实际答案远没有我用来弄清楚的步骤那么有趣。

    我编写了一个小 ruby​​ 脚本,只需要在 10 个线程中针对我们的应用发出 100 个请求(设置 jmeter 会比这花费更多时间)。 运行脚本并在运行时多次更改应用配置文件。这花了几分钟。 我使用进程资源管理器确认确实有 4 个应用程序域仍加载到进程中。 我运行了 procdump 并创建了一个转储文件。 将 procdump 文件加载到 Visual Studio 并单击“仅使用托管进行调试”(尽管我不知道该错误是否在托管代码中) 调试器在调用 Application_End 的线程正在等待队列完成处理的代码行上停止。通过查看变量的值,我得知队列不再处理项目,但我们将等到队列为空。 更改了代码并重新启动过程,这次我对 Web 配置的更改启动的所有应用程序域都已卸载。

【讨论】:

【参考方案2】:

您可以检查一件事,以帮助排除故障:

Process Explorer 实际上有一个.NET Assemblies 选项卡,其中列出了进程加载的所有 AppDomain。注意:该选项卡仅针对使用 .NET Framework 的进程显示。

【讨论】:

谢谢,因为用于列出应用程序域的代码在实时实例进程浏览器上由于某种奇怪的原因而失败,确实允许我查看 AppDomains。目前有 4 个。SharedDomain、DefaultDomain,然后是两个看起来像我们的应用程序的实例。 要是我知道是什么让应用程序域保持正常就好了。

以上是关于ASP.NET Web 应用程序在部署后不卸载 AppDomains的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Web 部署项目:摆脱 .compiled 文件

(转载)提高ASP.NET Web应用性能的技巧

提高 ASP.NET Web 应用性能的 24 种方法和技巧

使用弹性 beantalk 问题部署 Asp.net Web 应用程序

ASP.NET Web API 应用程序在 IIS 7 上部署时提供 404

在 Azure 上部署 Asp.NET Core Web App