【问题标题】:Asp.net Core process is not shutting down after IIS restarts siteIIS 重新启动站点后,Asp.net Core 进程未关闭
【发布时间】:2019-07-24 12:02:47
【问题描述】:

我有一个 IIS8 并且我已经部署了一个 asp.net 核心网站(使用 asp.net 核心模块)

为了不时更新站点的新功能,我将站点克隆到不同的文件夹并更改 Web 配置,以便 asp.net 核心模块从该文件夹启动应用程序。然后我将新文件复制到网站根目录中,并再次更改网络配置以指向根目录中的初始路径。

更改网络配置应该会触发(确实如此)应用程序重新启动。旧进程应该死掉(在正常关闭之后),而一个新进程(从新路径)应该启动。

问题是旧进程根本没有死。生成了一个新文件,但旧文件就在那里,我必须从任务管理器中手动将其杀死,否则我无法覆盖新文件。

我想,既然旧进程应该优雅地死掉,那么一定有一个长时间运行的请求来保持旧进程活着。我唯一想到的是我在浏览器页面中使用的 signalR 客户端保持与服务器的连接,因此它使旧进程保持活动状态。

为了验证这个理论,我在浏览器中打开了该站点,并在任务管理器中查看了任务。应用程序的过程就在那里。我更改了 Web 配置文件并在同一地址上打开了另一个选项卡。任务管理器中出现了一个新进程。但是几分钟过去了,旧的仍然在那里。我怀疑第一个浏览器选项卡与旧的 asp.net 核心进程保持连接。所以我关闭了第一个标签。在我关闭它后不到一秒钟,旧进程就被终止了。

那么我的理论正确吗? signalR 客户端是否会阻止 asp.net 核心进程在 web.config 更改后正常关闭?服务器 signalR 组件不应该向客户端发出断开连接(或发送断开连接事件)的信号,然后让进程终止吗?

我该如何克服这个问题?我希望在 web.config 更改后终止旧进程,而不是永远挂在那里并且不得不手动终止它。

【问题讨论】:

    标签: asp.net-core iis signalr


    【解决方案1】:

    很难准确地说,因为我从来没有考虑过做你正在做的事情,但我的感觉是这取决于更改 web.config。您实际上是在孤立另一个 Kestrel 进程。是的,更改 web.config 将触发重新启动,但它会在附加的进程中这样做。当 IIS 看到此更改的 web.config 时,它不会看到该位置的进程正在运行(因为您更改了位置),因此只需启动这个新进程。

    如果您已经部署到不同的文件夹,则只需在 IIS 中编辑站点并将文档根目录更改为该新目录。这将导致 IIS 停止当前正在运行的站点(即您现有的进程),然后再次启动它,但现在位于新的文档根位置。然后,您可以根据需要删除旧文件夹。

    【讨论】:

    • 我所做的工作适用于我拥有的许多其他 asp.net 核心站点(此解决方案是在线提出的,以克服 asp.net 核心中缺少卷影复制的问题)。我所做的是在将新站点文件复制到实际根目录期间使用带有旧版本站点的临时文件夹,然后切换回来。请注意,asp.net 核心对 web.config 一无所知。使用 web.config 并关闭应用程序的是 IIS。只是,在这个特定站点的情况下,进程并没有死亡,与其他工作站点的唯一区别是我有 signalR。
    • 归根结底,这里最初的问题是如何更新站点而不在文件复制过程中将其关闭。在经典的 asp.net 中,您可以覆盖整个文件层次结构,而 IIS 会处理所有事情。 Shadow Copying 会将文件复制到临时 asp 目录并从那里启动一个新进程 (AppDomain),而现有 AppDomain 将在处理所有未决请求后终止。由于应用程序从临时 asp 目录运行,因此根目录中没有文件被锁定。但在 asp.net core 中,应用程序从站点根目录运行,并且文件被锁定。
    • 我在回答中提出的解决方案解决了所有这些问题。没有锁定,零停机时间,而且我知道它可以正常工作。你正在做的事情可能很新颖,但我认为它不会一直有效。
    • 我也会尝试一下,看看会发生什么。