1

首先,我们编写了一个库,供 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 配置?

4

2 回答 2

1

您可以通过将 SharedConnection 和 AppDomain 清理代码放在Manager 对象的析构函数中来避免问题 a)。在管理器被释放并且不再被引用之后,或者当包含管理器的 AppDomain 被卸载时,垃圾收集器将只调用一次析构函数。这应该消除让您的清理线程被 IIS 中止的风险。(这可能算作对析构函数功能的滥用,但我不确定可能会产生什么负面后果(如果有的话。)

于 2013-07-31T00:23:47.307 回答
1

使用应用程序请求路由

为了解决完全相同的问题,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 将为您完成回收和管理应用程序池和管理域的工作,您不必做任何这些。

于 2013-08-02T11:37:31.003 回答