首页 > 解决方案 > 如何重新启动 Windows 服务中托管的 Kestrel?

问题描述

我想通过授权的 http 请求重新启动 Kestrel (asp.net core 3.1)。Kestrel 包含在配置为在失败时自动重新启动的 Windows 服务中。据我所知,最简单的方法是返回一个不同于 0 的退出代码,其余的全部由 Windows 完成。

鉴于此,我编写的代码实际上很简单:

        public MaintenanceController(IHostApplicationLifetime hostLifetime)
        {
            this.HostLifetime = hostLifetime ?? throw new ArgumentNullException(nameof(hostLifetime));
        }

        [HttpPost]
        [Route("service/restart")]
        [Authorize("AdminOnly")]
        public ActionResult RestartService()
        {
                Program.IsRestart = true; //see below
                this.HostLifetime.StopApplication();

                //this does not work!
                if (HostLifetime is WindowsServiceLifetime lifetime)
                {
                    lifetime.ExitCode = 1;
                }
                //neither this!
                Environment.ExitCode = 1;

                return Ok();
        } 

使Windows重新启动服务的唯一方法就是实际调用

Environment.Exit(1);

没有 HostLifetime.StopApplication();

但是单独调用 Environment.Exit 的问题是它会导致正常关闭,这是我绝对要避免的。

我尝试的另一种方法是强制一个不同于 0 的退出代码,但它不起作用,是放入 Startup.cs:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime)
        {
            [...]

            applicationLifetime.ApplicationStopped.Register(() =>
            {
                //this can be set in the controller
                if (Program.IsRestart)
                {
                    Environment.Exit(1); 
                }
            });
        }

但是,当在 ApplicationStopped 之后调用时,Environment.Exit(1) 显然什么都不做,事实上,即使在事件查看器内部,也没有服务因错误而关闭的痕迹,所以 windows 什么也不做。

更新

回到经典,我将 Main 入口点更改为返回一个 int 并返回 1。Windows 仍然不会重新启动服务,也不会将失败条目写入事件查看器。看起来总是优雅地停止

标签: asp.net-core.net-corewindows-serviceskestrel-http-server

解决方案


一切都按应有的方式工作。您可能需要考虑编写一个包装批处理文件或观察程序。

您的观察者将等待进程退出,并且如果存在标志文件(例如.staydown),它将正常退出。如果该文件不存在,它将重新启动该过程。

在您的RestartService方法中,使用Environment.Exit(0)which 将是正常关闭,但由于该.staydown文件不存在,您的观察者将重新启动服务器。.staydown仅当文件存在然后服务器停止或 Windows 服务本身停止时,您的观察程序才会停止运行。

当您的应用启动时,请务必删除(.staydown如果存在)。

如果您安装了节点,您也许可以使用一个实用程序forever来代替观察程序批处理文件。


推荐阅读