在IIS中创建自定义AppDomains会阻止其发布,并使网站陷入僵局
本文关键字:陷入僵局 网站 创建 IIS 自定义 AppDomains | 更新日期: 2023-09-27 18:25:31
首先,我们编写了一个由Windows服务使用的库,以及一个在IIS 7中运行的ASP网页。
该库需要将其他库作为插件加载,但一些外部库的名称相同(但内部版本不同)。为了解决这个二进制名称空间冲突,我们为每个插件创建了一个AppDomain。Library有一个Manager对象,它引用一个静态连接池。在静态SharedConnection池中,AppDomains是活动的,并且被销毁。删除最后一个Manager对象后,Manager对象将调用SharedConnection的清理。此清理将释放我们创建的AppDomains。
依靠我们图书馆的服务部门处理得很好。在其生命周期开始时,它会创建AppDomains,并在结束时在清理过程中删除它们。
依赖我们图书馆的网站处理得很差。在其生命周期开始时,它会创建AppDomains,但是,当IIS在一段时间不活动后决定卸载我们时,Manger对象会被删除,这会按预期调用SharedConnection对象的清理。这反过来又会关闭AppDomains。
有两个问题
a) 我们在连接和AppDomain发布时使用lock()
,因此它们不会发布两次并随后引发错误。除某些原因外,在极少数情况下,进入锁并杀死AppDomain的线程将不存在,并且永远不会离开锁,从而导致死锁场景。解决此问题的唯一方法是停止IIS中的AppPool,并在30-60秒后重新启动它。Windows服务不会发生这种情况。
b) 当我们没有观察到上述情况时(这种情况很少发生),相反,偶尔我们会遇到AppDomain发布问题,这会引发异常,导致网页崩溃并重新启动,这还可以。
我通过调试发现的其他东西。IIS将网站放在自己的AppDomain中,这意味着我们是一个生成更多子AppDomain的子AppDomain。
我们做错了什么?是否有可能有所帮助的IIS配置?
使用应用程序请求路由
为了解决完全相同的问题,IIS创建了ARR,根据URL、Cookie或Header参数将请求路由到特定版本的应用程序,该参数可以轻松配置。ARR作为HTTP代理服务器工作,它执行简单的路由。
这是一个例子,
http://blogs.msdn.com/b/carlosag/archive/2010/04/02/setting-up-a-reverse-proxy-using-iis-url-rewrite-and-arr.aspx
IIS将为您完成回收和管理应用程序池以及管理域的工作,您不必做任何这些。
您可以通过将SharedConnection和AppDomain清理代码放在Manager对象的析构函数中来避免问题a)。在管理器被释放且不再被引用后,或者在卸载包含管理器的AppDomain时,垃圾收集器将只调用一次析构函数。这应该可以消除IIS中止清理线程的风险。(这可能被视为对析构函数功能的滥用,但我不确定可能会产生什么负面后果。)