使用.NET Core Application优雅地处理AWS ECS停止任务

Tre*_*ley 5 c# amazon-web-services amazon-ecs .net-core

我编写了一个.NET核心控制台应用程序,作为AWS ECS Fargate中的任务运行.基本上,控制台应用程序启动一个处理线程,然后需要继续运行(很像Kestrel Web主机.)

最初,我放入一个Console.ReadKey(),认为它永远不会命中,应用程序将继续运行.那导致.NET异常......

Cannot read keys when either application does not have a console 
or when console input has been redirected. Try Console.Read.
Run Code Online (Sandbox Code Playgroud)

所以我然后用Console.Read()替换ReadKey.应用程序的行为就像它不存在,继续移动,应用程序一开始就退出.

通过研究,我发现了Console.CancelKeyPress事件.我实现了它,它的工作原理是控制台应用程序将继续运行.

ManualResetEvent _quitEvent = new ManualResetEvent(false);
Console.CancelKeyPress += (sender, eArgs) => {
                Console.WriteLine("Shutting down.");
                _quitEvent.Set();
                eArgs.Cancel = true;
            };
_quitEvent.WaitOne();
Run Code Online (Sandbox Code Playgroud)

但是,当发生这种情况时,我想优雅地处理应用程序的关闭.

通过进一步的研究,我发现当AWS ECS停止任务时,它不会发送Ctrl-C(SIGINT)而是发送SIGTERM. https://docs.aws.amazon.com/cli/latest/reference/ecs/stop-task.html

然后我实现我认为是.NET中SIGTERM的标准事件处理(见下文).

AssemblyLoadContext.Default.Unloading += ctx =>
            {
                Console.WriteLine("Shutting down.");
                _quitEvent.Set();
            };
_quitEvent.WaitOne();
Run Code Online (Sandbox Code Playgroud)

这在ECS中编译并运行良好.但是......我通过AWS ECS控制台点击"停止"按钮,它停止任务并重新启动新任务.当我查看该停止任务的日志时,没有关闭日志消息,没有正常关闭的指示,什么也没有.它似乎只是被迫杀死了.

我在这里错过了什么吗?我可以做些什么来优雅地捕获AWS ECS中的停止任务以优雅地关闭任务?

Imr*_*ran 4

看起来它与处理正常关闭的 .net 代码有关。我刚刚在本地使用以下代码、docker 和 ECS Stop-Task 进行了测试。在所有地方,我都得到了优雅的关闭。我没有完整的代码,所以我创建了自己的示例。

using System;
using System.Runtime.Loader;
using System.Threading;

namespace consoleapp
{
    class Program
    {
        static void Main(string[] args)
        {
            var _quitEvent = new ManualResetEvent(false);
            AssemblyLoadContext.Default.Unloading += ctx =>
            {
                System.Console.WriteLine("Unloding fired");
                _quitEvent.Set();
            };
            System.Console.WriteLine("Waiting for signals");
            _quitEvent.WaitOne();
            System.Console.WriteLine("Received signal gracefully shutting down");
            Console.WriteLine("Hello World!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想自己尝试,请参阅完整的 github 存储库参考。 https://github.com/imran9m/netconsoleapp.git

您应该看到容器的示例日志。

等待信号

卸货被解雇

收到信号正常关闭

你好世界!

注意 - 要在本地测试 SIGTERM 信号,您需要kill -SIGTERM {PID}在 dotnet CLI 上运行而不是运行 CTRL+C。