Kestrel Shutdown Function in Startup.Cs in ASP.NET Core

Kestrel shutdown function in Startup.cs in ASP.NET Core

In ASP.NET Core you can register to the cancellation tokens provided by IApplicationLifetime

public class Startup 
{
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
{
applicationLifetime.ApplicationStopping.Register(OnShutdown);
}

private void OnShutdown()
{
// Do your cleanup here
}
}

IApplicationLifetime is also exposing cancellation tokens for ApplicationStopped and ApplicationStarted as well as a StopApplication() method to stop the application.

For .NET Core 3.0+

From comments @Horkrine

For .NET Core 3.0+ it is recommended to use IHostApplicationLifetime instead, as IApplicationLifetime will be deprecated soon. The rest will still work as written above with the new service

.NET Core 6.0 - Get Kestrel's dynamically bound port (port 0)

Found a working answer right after posting the question.
Function to print the address of a runing web server (including port) in .NET 6.
Turns out we're interested in a running instance of a IServer service in the host.

public static void PrintBoundAddressesAndPorts(IHost host)
{
Console.WriteLine("Checking addresses...");
var server = host.Services.GetRequiredService<IServer>();
var addressFeature = server.Features.Get<IServerAddressesFeature>();
foreach(var address in addressFeature.Addresses)
{
var uri = new Uri(address);
var port = uri.Port;
Console.WriteLine($"Listing on [{address}]");
Console.WriteLine($"The port is [{port}]");
}
}

Found the answer in this article: https://andrewlock.net/finding-the-urls-of-an-aspnetcore-app-from-a-hosted-service-in-dotnet-6/

Preform cleanup when Kestrel is stopped for any reason in ASP.Net Core 2.0

Event handling is predicated on a successful exit. If you do something like a hard reboot or your application crashes, there's no opportunity to handle anything because it's already gone. That's sort of the point: it was forced to exit, so it can't do anything.

That said, the issue here is either not actually an issue or a design problem. First, if the process exits, the threads go with it. There's nothing to "cleanup". Socket handles and such are just pointers in memory, they too go with the process.

If the process is hanging, that's a different story. In that situation, it can hold on to resources, since it's still technically running. However, then, the true issue is fixing whatever is causing the process to hang, not figuring out how to release resources when it does.

Bear in mind that a web server is designed to quickly respond to incoming requests. It should be an almost instantaneous process. It's not designed to chew on requests for a while, doing a bunch of work. If you need to do things like connect to sockets and such, that should very likely be offloaded into an external process, like a console application, windows service, etc. Then, your web application can simply hand off work to this and move on. You can provide an endpoint to check for status, progress, etc., and use that via SignalR or AJAX long-polling to update the client about the progress of the work/notify them when it's done.

Can kestrel server in ASP.NET core be configured with idle timeout at startup

When you use IIS as a reverse proxy for an ASP.NET Core application, IIS starts the process and that idle timeout on the app pool decides when to shut down the process. IIS knows that there are no active requests, and it will just kill the process without asking the process for permission. So there is no way for your application to stop that. (You have to be aware of that if you run any background jobs in your application - IIS doesn't know about those and could kill your app in the middle of something running)

If you run without IIS, it would never automatically shut down at all, since shutting down means that nothing is listening for new connections anymore. That's the benefit of using IIS: it can restart your application if there is a catastrophic failure.

So if you plan on keeping your application behind IIS, and you want it to never shut down, then you will have to get the settings on the app pool changed.

Where can I log an ASP.NET Core app's start/stop/error events?

Note: For .NET Core 3.0 or later, this answer is obsolete. See this answer instead.

You need to use Microsoft.AspNetCore.Hosting.IApplicationLifetime

    /// <summary>
/// Triggered when the application host has fully started and is about to wait
/// for a graceful shutdown.
/// </summary>
CancellationToken ApplicationStarted { get; }

/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// Requests may still be in flight. Shutdown will block until this event completes.
/// </summary>
CancellationToken ApplicationStopping { get; }

/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// All requests should be complete at this point. Shutdown will block
/// until this event completes.
/// </summary>
CancellationToken ApplicationStopped { get; }

Instance of IApplicationLifetime could be obtained in Configure method. Also add ILoggerFactory here:

public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory)
{
// use applicationLifetime
}

Having ILoggerFactory, you can create instance of ILogger:

var logger = loggerFactory.CreateLogger("StartupLogger"); 

So you just need to create a property in the Startup class to persist the instance of ILogger (or ILoggerFactory, if you would like to create different ligger instance for different events). To summarize:

public class Startup 
{
private ILogger _logger;

public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory)
{
applicationLifetime.ApplicationStopping.Register(OnShutdown);
...
// add logger providers
// loggerFactory.AddConsole()
...
_logger = loggerFactory.CreateLogger("StartupLogger");
}

private void OnShutdown()
{
// use _logger here;
}
}

graceful shutdown asp.net core

For capturing graceful shutdown, you could try IHostApplicationLifetime.

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading;

namespace Microsoft.Extensions.Hosting
{
/// <summary>
/// Allows consumers to be notified of application lifetime events. This interface is not intended to be user-replaceable.
/// </summary>
public interface IHostApplicationLifetime
{
/// <summary>
/// Triggered when the application host has fully started.
/// </summary>
CancellationToken ApplicationStarted { get; }

/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// Shutdown will block until this event completes.
/// </summary>
CancellationToken ApplicationStopping { get; }

/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// Shutdown will block until this event completes.
/// </summary>
CancellationToken ApplicationStopped { get; }

/// <summary>
/// Requests termination of the current application.
/// </summary>
void StopApplication();
}
}

A demo:

public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var life = host.Services.GetRequiredService<IHostApplicationLifetime>();
life.ApplicationStopped.Register(() => {
Console.WriteLine("Application is shut down");
});
host.Run();
}

Port not freed as soon as program exist in c# .net core

When you close a NetCore application it doesnt call code to terminate the running service. It just terminates, which means the code isn't called to close the connection. You need to make sure any code which opens a port is wrapped in a using so that it can dispose correctly. In a Windows Service, there should be a method for OnStop which you need to handle and explicitly close the connection.

https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicebase.onstop?view=dotnet-plat-ext-6.0

If the problem still happens, the only way I've found to resolve it is to reboot my machine



Related Topics



Leave a reply



Submit