How to graceful shutdown web app when it exceeds start time limit in Azure App Service?

huangapple go评论73阅读模式
英文:

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 CancellationTokens. 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.

How to graceful shutdown web app when it exceeds start time limit in Azure App Service?

How to graceful shutdown web app when it exceeds start time limit in Azure App Service?

How to graceful shutdown web app when it exceeds start time limit in Azure App Service?

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) =&gt;
    {
        Program.IsShuttingDown = true;
    };

}

Check the IsShuttingDown flag to perform a graceful shutdown in IHostedService.

public class LongRunningInitializationService : IHostedService
{
    private readonly ILogger&lt;LongRunningInitializationService&gt; _logger;
    private readonly CancellationTokenSource _cancellationTokenSource;

    public LongRunningInitializationService(ILogger&lt;LongRunningInitializationService&gt; logger)
    {
        _logger = logger;
        _cancellationTokenSource = new CancellationTokenSource();
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _cancellationTokenSource.Token to check for cancellation requests
        Task.Run(() =&gt; DoInitialization(), _cancellationTokenSource.Token);
        return Task.CompletedTask;
    }

    private async Task DoInitialization()
    {
        try
        {
            while (!Program.IsShuttingDown)
            {
                await Task.Delay(1000);
                _cancellationTokenSource.Token.ThrowIfCancellationRequested();
            }

           _logger.LogInformation(&quot;Initialization completed.&quot;);
        }
        catch (OperationCanceledException)
        {
          _logger.LogWarning(&quot;Initialization canceled.&quot;);
        }
    }

    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.

huangapple
  • 本文由 发表于 2023年6月26日 15:45:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76554557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定