当 IIS 重新启动 ASP.Net (2.0) Web 应用程序时,它可以:
- 回收 AppDomain:卸载 AppDomain 并在同一进程上加载新的 AppDomain(例如,当当 web.config 更改时,将调用
HttpRuntime.UnloadAppDomain()
)。
- 回收进程:卸载AppDomain并在新进程上加载新的AppDomain(例如,当通过inetmgr在AppPool上调用Recycle命令时,或者达到内存限制时)。
由于一些内部原因(我们所依赖的遗留本机代码出现问题),我们不能允许第一个选项。我们只是不能在同一个进程上加载应用程序两次。
是否可以以某种方式告诉 IIS 永远不允许工作进程重用?
我自己尝试过通过跟踪应用程序是否已经在使用互斥锁的进程上启动来防止这种情况发生,如果是,则在 Application_Start()
期间抛出异常);我还尝试通过在 Application_End()
期间调用 Environment.Exit()
来终止该进程。这两种方法的问题在于,它会导致在 Application_End 或 Application_Start 期间到达的任何请求失败(与手动进程回收不同,手动进程回收绝对不会失败任何请求,因为它们会立即重定向到新进程)。
When IIS restarts an ASP.Net (2.0) web application, it can either:
- Recycle the AppDomain: Unload the AppDomain and load a new AppDomain on the same process (e.g. when
HttpRuntime.UnloadAppDomain()
is called, when web.config is changed).
- Recycle the process: unload the AppDomain and load a new one on a new process (e.g. when invoking Recycle command on an AppPool via inetmgr, or when memory limit is reached).
Due to some internal reasons (trouble with legacy native code we depend upon), we cannot allow the first option. We just can't load the application twice on the same process.
Can IIS be somehow told to never allow worker process reuse?
I've tried preventing it myself by tracking whether an application has already started on a process once using a Mutex, and if so - throwing an exception during Application_Start()
); I've also tried terminating the process by calling Environment.Exit()
during Application_End()
. The problem with both methods is that it causes any requests that arrive during Application_End or Application_Start to fail (unlike a manual process recycle, which fails absolutely no requests because they are redirected to the new process right away).
发布评论
评论(2)
我相信“回收 AppDomain”属于 ASP.NET 运行时的预览版,并且 IIS 并没有真正参与到任何地方(对于 IIS7 的集成管道,我对此不是 100% 确定)。所以我不认为你想要的是可行的。但是,您可以考虑解决问题的几种解决方法:
确保运行启动代码(操作遗留代码)仅运行一次 - 这应该可以通过命名系统信号量。一旦应用程序在工作进程中启动创建了系统信号量,它将一直存在,直到进程被回收,以便您可以对每个进程进行初始化。
如果#1 不可能,则考虑在单独的进程中托管代码来操作遗留代码 - 该进程可以通过命名管道上的 WCF 服务公开相关功能。 ASP.NET 将使用它们来使用遗留代码。
I believe that "Recycle the AppDomain" comes under preview of ASP.NET runtime and IIS is not really involved anywhere (I am not 100% sure about this in case of integrated pipeline of IIS7). So I don't think that what you want is feasible. But there are couple of workaround that you may consider for your problem:
Ensure that you run start-up code (manipulating legacy code) to run only once - this should be possible via named system semaphores. Once system semaphore is created by app start-up in worker process, it will exists till process is recycled so you can have per process initialization.
If #1 is not possible then consider hosting code manipulating legacy code in a separate process all together - this process can expose relevant functionality via WCF services over named pipes. ASP.NET will consume them to use legacy code.
找不到告诉 IIS 工作进程不被重用的方法。无法修复禁止进程重用的根本问题。因此,最终在
Application_End
中调用Environment.Exit(0)
,尽管这可能会导致少量请求因连接重置而失败。Couldn't find a way to tell IIS that worker processes are not to be reused. Can't afford fixing the underlying problem that forbids process reuse. Therefore, ended up calling
Environment.Exit(0)
inApplication_End
, although it may cause a small number of requests to fail with a connection reset.