首先,我们编写了一个库,供 Windows 服务使用,以及在 IIS 7 中运行的 ASP 网页。
该库需要将其他库作为插件加载,但一些外部库具有相同的名称(但内部版本不同)。为了解决这个二进制命名空间冲突,我们为每个插件创建了一个 AppDomain。Library 有一个 Manager 对象,它引用了一个静态连接池。在静态 SharedConnections 池中,AppDomain 存在并被销毁。当最后一个 Manager 对象被删除时,Manager 对象调用 SharedConnections 的清理。此清理会释放我们创建的 AppDomain。
依赖于我们图书馆的服务可以很好地处理这个问题。在其生命周期开始时,它会创建 AppDomain,并在结束时在清理期间将其删除。
依赖我们图书馆的网站处理得不好。在其生命周期的开始,它会创建 AppDomain,但是当 IIS 在一段时间不活动后决定卸载我们时,Manger 对象将被删除,这会按预期调用 SharedConnection 对象的清理。这反过来又杀死了 AppDomains。
有两个问题
a) 我们使用lock()
围绕连接和 AppDomain 发布,因此它们不会发布两次并随后引发错误。除非出于某种原因,在极少数情况下,进入锁并杀死 AppDomain 的线程不复存在,并且永远不会离开锁,从而导致死锁场景。我们可以解决此问题的唯一方法是停止 IIS 中的 AppPool 并在 30-60 秒后重新启动它。Windows 服务不会发生这种情况。
b)当我们没有观察到上述情况(这种情况很少发生)时,偶尔我们会遇到 AppDomain 发布问题,这会引发崩溃并重新启动网页的异常,这没关系。
我通过调试发现的其他内容。IIS 将网站放置在它自己的 AppDomain 中,这意味着我们是一个子 AppDomain,生成了更多的子 AppDomain。
我们做错了什么?是否有可能有帮助的 IIS 配置?