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

7
当我们部署web应用程序时,我们将所有代码复制到一个新目录中,然后将iis指向该新目录。这样做会增加appdomains的数量,但从不减少。此外,我们的Application_End事件似乎从未触发过。
在某个未知的时间内,尽管perfmon仍报告两组AppDomains,但系统表现非常差,同时GC时间百分比飙升到100%。最终,为了使应用程序再次顺畅运行,我重新启动应用程序池。
额外的信息:在我的开发机上列出应用程序域时显示为2个,在现场服务器上运行4个...我们只有一个应用程序在池中运行,这意味着我们使用的某个库正在创建应用程序域。
我应该怎么做来调试发生的情况?什么会阻止应用程序域卸载?
2021年10月12日更新:
在获得更多详细日志信息后,看起来问题并不是旧的应用程序域仍然存在,而是在重启期间创建了新的应用程序域。应用程序不是启动一个新实例,而是启动两个。有时我们从旧实例获取application_end,有时没有。
2021年10月13日更新:
两件事都发生了。使用进程资源管理器,我可以看到一台机器上仍有旧的应用程序域,而新的应用程序域已经启动。在另一台机器上,只有2个应用程序域,但它们的顺序编号中间出现了断层。因此,启动了两个实例(我们还从应用程序启动获得日志消息),其中一个几乎立即关闭,留下了2个应用程序域。

你是否使用带有驱逐方案的ASP.NET缓存来重新加载过期缓存? - Erik Funkenbusch
我们确实使用ASP.NET应用程序缓存。我们根据用户会话超时设置滚动过期时间来插入内容。但它不会自动重新加载任何内容。 - Russell Clarvoe
“滚动过期”是什么意思?你是指更新过期时间吗?我的问题是,当基于缓存管理器的回调函数对象过期时,您是否重新加载缓存? - Erik Funkenbusch
如果缓存键在x分钟内没有被访问,则从缓存中删除该项。缓存管理器不会重新加载项目到缓存中。只有用户发出请求时,这些项目才会被放回缓存中。 - Russell Clarvoe
2个回答

3
尽管我不确定应用程序没有卸载应用程序域的唯一原因是什么,但这确实是其中一个原因。实际答案比我用来找到它的步骤更少趣味。
以下是我用来找到问题的步骤:
1. 我编写了一个小的ruby脚本,只需在10个线程中对我们的应用程序进行100次请求(设置jmeter需要更多时间)。 2. 运行脚本并在其运行时多次更改应用程序配置文件。这需要几分钟时间。 3. 我使用进程资源管理器确认有4个应用程序域确实加载到进程中。 4. 我运行了procdump并创建了一个转储文件。 5. 将procdump文件加载到Visual Studio中并单击“仅使用托管调试”(尽管我不知道错误是否在托管代码中)。 6. 调试器停在调用Application_End的线程等待队列完成处理的代码行上。通过查看变量的值,我能够确定队列将不再处理项目,但我们将等待队列为空。 7. 更改代码并重新启动进程,这次所有由我的Web配置更改启动的应用程序域都已卸载。

2

如果需要进行故障排除,您可以检查以下内容:

Process Explorer 实际上有一个 .NET Assemblies 选项卡,列出了进程加载的所有应用程序域。注意:此选项卡仅适用于使用 .NET Framework 的进程。


谢谢,因为在实例中列出应用程序域的代码由于某种奇怪的原因而失败,但进程资源管理器确实允许我查看AppDomains。目前有4个,SharedDomain、DefaultDomain,以及两个看起来像我们的应用程序的实例。 - Russell Clarvoe
如果我知道是什么让应用程序域保持运行状态就好了。 - Russell Clarvoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接