正常关闭IHostedService

时间:2018-08-01 13:31:06

标签: c# iis asp.net-core iis-7.5

我正在尝试在.NET Core中开发一个简单的API,以允许异步处理请求。

  1. 请求已发送至控制器
  2. 在后台服务(IHostedService)上安排的工作
  3. 控制器返回202
  4. 后台服务执行长时间运行的操作

由于应用程序将在IIS上运行,因此控制器返回响应后,可能会发生池回收。我想实现一种允许应用程序正常关闭的方法-完成它当前正在执行的任务,但不接受任何新任务。

我无法正常关闭关机。 为了测试目的,我简化了StopAsync()方法,因此现在它只包含一个异步20秒等待时间:

public async Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Hosted service is stopping...");

        try
        {
            // Signal cancellation to the executing method
            _stoppingTokenSource.Cancel();

            _logger.LogInformation("Delay by 20s");
            await Task.Delay(20000, cancellationToken);
            _logger.LogInformation("Delay over");
        }
        finally
        {
            // Await all pending download requests
            await Task.WhenAny(Task.WhenAll(_pendingTasks), Task.Delay(Timeout.Infinite, cancellationToken));

            _logger.LogInformation("Hosted service has been stopped successfully.");
        }
    }

仅显示日志:

  • 托管服务正在停止...
  • 延迟20秒

查看 EventViewer ,我可以看到在关闭之间恰好有10秒的时间触发了2个事件:

  • 发送关闭HTTP消息以处理'11104',并收到http状态'202'。
  • 无法正常关闭进程'11104'。

我已经尝试过:

设置Program.cs上的关闭超时

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseShutdownTimeout(TimeSpan.FromMinutes(1));

检查应用程序池的高级设置:

enter image description here

如果您做了类似的事情,能否请我知道我做错了什么/指出正确的方向吗?

谢谢!

编辑

在调试应用程序时,使用CTRL + C关闭会产生预期的行为。

2 个答案:

答案 0 :(得分:3)

再次查看问题后,我找到了解决方案。

似乎IIS中的ASP.NET Core模块有一个单独的关闭时间限制,可以在web.config文件中将其配置为:

<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore
        shutdownTimeLimit="30"   <--- set timeout here in seconds
        processPath="dotnet"
        arguments=".\GracefulShutdown.dll"
        stdoutLogEnabled="false"
        stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>

参考以下设置: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-2.1

理想情况下,这应该可以通过代码获得,这仍然是我要解决的问题。如果您找到解决方法,请发表评论。

答案 1 :(得分:2)

在Configure(IApplicationBuilder app,IHostEnvironment env)函数中 在IHostApplicationLifetime中注册到ApplicationStopping(在应用程序主机执行正常关机时触发。关机将阻止,直到该事件完成为止)

  var applicationLifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
  applicationLifetime.ApplicationStopping.Register(OnShutdown);

private void OnShutdown() { 在关机之前在此处编写您想要的代码,您可以通过Thread.Sleep();延迟关机。 }