Reputation: 61
I'm working on graceful shutdown for ASP.NET Core 2.1. I noticed that all requests which are in flight on Controller will be canceled in a moment when the Graceful shutdown starts. Even if I want all requests to be successfully finished before Container will be disposed.
According to IApplicationLifetime https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iapplicationlifetime?view=aspnetcore-2.1
ApplicationStopping Triggered when the application host is performing a graceful shutdown. Requests may still be in flight. Shutdown will block until this event completes.
What can I do to prevent disposing before all my current requests will be finished?
Example:
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();
}
Controller:
public class UserOrdersController : Controller
{
public async Task<IActionResult> GetUserOrders(string productId)
{
await Task.Delay(5000);
Console.WriteLine("Finished");
//.....................................
}
}
So "Finished" will not be printed if I ask to perform graceful shutdown.
UPD:
Added .UseShutdownTimeout(TimeSpan.FromSeconds(10))
to builder but it did not help.
Upvotes: 5
Views: 8198
Reputation: 360
Like others have mentioned, your desired behavior should happen out of the box. SIGINT should trigger a graceful shutdown. I have a feeling you're testing by running a Task.Delay that is longer than the web host's default shutdown timeout value. This would cause the timeout to be triggered, which will kill all the currently running requests.
Set the web hosts shutdown timeout like so:
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>();
}
}
Upvotes: 4
Reputation: 403
I recommend executing IWebHost.RunAsync passing in CancellationToken so that when SIGINT and Ctrl+C commands are sent to your app you can intercept and Cancel the token which will result in a graceful shutdown of the application.
See the following code example:
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);
}
}
Upvotes: 1