英文:
How to graceful shutdown web app when it exceeds start time limit in Azure App Service?
问题
在Azure应用服务中,我有一个ASP.NET Core Web应用程序,它在开始接收请求之前需要进行长时间的初始化。初始化可能需要比WEBSITES_CONTAINER_START_TIME_LIMIT中设置的时间更长。当这种情况发生时,Azure应用服务会终止该应用程序。
我希望Azure应用服务尝试通过发送SIGTERM信号来优雅地停止应用程序。
我已将所有长时间初始化的操作提取到一个IHostedService的实现中,并使用CancellationToken。我在本地机器上进行了测试,当这个初始化操作正在运行时,我发送了SIGTERM信号,它会优雅地关闭,但Azure应用服务仍然会终止该应用程序。
看起来Azure应用服务似乎不会尝试使用SIGTERM来终止应用程序,而是直接发送SIGKILL信号。
英文:
In Azure App Service
I have a ASP.NET Core
web app that can need to do a long running initialization before it starts receiving requests. The initialization can take more time than set in WEBSITES_CONTAINER_START_TIME_LIMIT
. When it happens AAS
kills the app.
I want AAS
try to gracefully stop the app via sending SIGTERM
signal.
I've extracted all long running initialization to an implementation of IHostedService
and use CancellationToken
s. I tested it on a local machine via sending SIGTERM
while this initialization was running and it gracefully shutdowned, but AAS
stills kill the app.
It looks like AAS
doesn't try to SIGTERM
the app and just sends SIGKILL
.
答案1
得分: 1
Azure App Service在超过启动时间限制时不会发送SIGTERM信号以正常关闭Web应用程序。它通过发送SIGKILL信号来终止进程。
在Azure中,可以通过更改应用程序配置来实现这一点。
您可以实施一种解决方案来处理在超过启动时间限制时进行正常关闭。
更新您的ASP.NET Core Web应用程序项目中的Program.cs文件。
创建一个静态变量来跟踪应用程序是否正在正常关闭。
public static class Program
{
public static bool IsShuttingDown { get; private set; }
public static void Main(string[] args)
{
}
}
修改Main方法以设置SIGTERM处理程序。
public static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) =>
{
Program.IsShuttingDown = true;
};
}
在IHostedService中检查IsShuttingDown
标志以执行正常关闭。
public class LongRunningInitializationService : IHostedService
{
private readonly ILogger<LongRunningInitializationService> _logger;
private readonly CancellationTokenSource _cancellationTokenSource;
public LongRunningInitializationService(ILogger<LongRunningInitializationService> logger)
{
_logger = logger;
_cancellationTokenSource = new CancellationTokenSource();
}
public Task StartAsync(CancellationToken cancellationToken)
{
// 使用_cancellationTokenSource.Token来检查取消请求
Task.Run(() => DoInitialization(), _cancellationTokenSource.Token);
return Task.CompletedTask;
}
private async Task DoInitialization()
{
try
{
while (!Program.IsShuttingDown)
{
await Task.Delay(1000);
_cancellationTokenSource.Token.ThrowIfCancellationRequested();
}
_logger.LogInformation("Initialization completed.");
}
catch (OperationCanceledException)
{
_logger.LogWarning("Initialization canceled.");
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
}
如果Azure App Service超过启动时间限制,然后发送SIGKILL信号来终止进程。
而Main方法中的SIGTERM处理程序将设置IsShuttingDown
标志,允许LongRunningInitializationService
通过取消初始化过程执行正常关闭。
Azure App Service具有超时机制,如果关闭过程时间超过超时期限,仍将导致强制终止。
有关更多信息,请参阅MS Doc。
英文:
>Azure App Service does not send a SIGTERM signal to gracefully shut down a web app when it exceeds the start time limit. It terminates the process by sending a SIGKILL signal.
In Azure, by changing the App configuration it can be done.
You can implement a workaround to handle graceful shutdowns when the start time limit is exceeded.
Update the Program.cs file in your ASP.NET Core web app project.
Create a static variable to track whether the application is shutting down gracefully.
public static class Program
{
public static bool IsShuttingDown { get; private set; }
public static void Main(string[] args)
{
}
}
Modify the Main method to SetUp a SIGTERM handler.
public static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) =>
{
Program.IsShuttingDown = true;
};
}
Check the IsShuttingDown
flag to perform a graceful shutdown in IHostedService.
public class LongRunningInitializationService : IHostedService
{
private readonly ILogger<LongRunningInitializationService> _logger;
private readonly CancellationTokenSource _cancellationTokenSource;
public LongRunningInitializationService(ILogger<LongRunningInitializationService> logger)
{
_logger = logger;
_cancellationTokenSource = new CancellationTokenSource();
}
public Task StartAsync(CancellationToken cancellationToken)
{
_cancellationTokenSource.Token to check for cancellation requests
Task.Run(() => DoInitialization(), _cancellationTokenSource.Token);
return Task.CompletedTask;
}
private async Task DoInitialization()
{
try
{
while (!Program.IsShuttingDown)
{
await Task.Delay(1000);
_cancellationTokenSource.Token.ThrowIfCancellationRequested();
}
_logger.LogInformation("Initialization completed.");
}
catch (OperationCanceledException)
{
_logger.LogWarning("Initialization canceled.");
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
}
If the Azure App Service exceeds the start time limit then it sends a SIGKILL signal to terminate the process.
And the SIGTERM handler in the Main method will set the IsShuttingDown
flag, allowing the LongRunningInitializationService
to perform a graceful shutdown by cancelling the initialization process.
>Azure App Service has a timeout mechanism, and if the shutdown process takes longer than the timeout period, it still result in a forced termination.
For more information, refer to MS Doc.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论