正常关机和当前正在处理的请求

时间:2018-07-23 15:54:14

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

我正在为ASP.NET Core 2.1正常关机。 我注意到,在正常关机开始时,Controller上正在运行的所有请求都将被取消。 即使我希望在处理容器之前成功完成所有请求。

根据 IApplicationLifetime https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iapplicationlifetime?view=aspnetcore-2.1

  

ApplicationStopping 在应用程序主机执行时触发   正常关机。请求可能仍在进行中。关机将   阻止,直到此事件完成为止。

我该怎么做才能在我所有当前请求完成之前阻止处理?

示例:

public static void Main(string[] args) { 
    WebHostExtensions.Run(BuildWebHost(args));
}

private static IWebHost BuildWebHost(string[] args) {
    return WebHostExtensions.CreateDefaultBuilder(args)
        .UseSerilog()
        .UseStartup<Startup>()
        .UseUrls("http://0.0.0.0:9100")
        .Build();
}

控制器:

public class UserOrdersController : Controller
{
     public async Task<IActionResult> GetUserOrders(string productId)
     {
         await Task.Delay(5000);
         Console.WriteLine("Finished");
         //.....................................
     }        
}

因此,如果我要求执行正常关机,则不会打印“完成”

UPD: 向构建器添加了.UseShutdownTimeout(TimeSpan.FromSeconds(10)),但没有帮助。

2 个答案:

答案 0 :(得分:1)

就像其他人提到的那样,您期望的行为应该开箱即用。 SIGINT应该触发正常关机。我感觉您正在通过运行比Web主机的默认关机超时值更长的Task.Delay进行测试。这将导致超时触发,这将终止所有当前正在运行的请求。

设置网络主机关闭超时,如下所示:

public class Program
{
  public static void Main(string[] args)
  {
    CreateWebHostBuilder(args).Build().Run();
  }

  public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
      WebHost.CreateDefaultBuilder(args)
      .UseShutdownTimeout(TimeSpan.FromSeconds(60)) // set timeout value here
          .UseStartup<Startup>();
  }
}

答案 1 :(得分:0)

我建议执行传递CancellationToken的IWebHost.RunAsync,以便在将SIGINT和Ctrl + C命令发送到您的应用程序时,您可以拦截和取消该令牌,这将导致应用程序正常关闭。

请参见以下代码示例:

public class Program
{
    private static readonly CancellationTokenSource cts = new CancellationTokenSource();

    protected Program()
    {
    }

    public static int Main(string[] args)
    {
        Console.CancelKeyPress += OnExit;
        return RunHost(configuration).GetAwaiter().GetResult();
    }

    protected static void OnExit(object sender, ConsoleCancelEventArgs args)
    {
        cts.Cancel();
    }

    static async Task<int> RunHost()
    {
        await new WebHostBuilder()
            .UseStartup<Startup>()
            .Build()
            .RunAsync(cts.Token);
    }
}