我编写了一个.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.
因此我将ReadKey替换为Console.Read()。该应用程序的行为就像它还没有出现一样,一直在移动,并且在启动后立即退出。
通过研究,我发现了Console.CancelKeyPress事件。我实现了它,并且它在控制台应用程序将继续运行的事实中起作用。
ManualResetEvent _quitEvent = new ManualResetEvent(false);
Console.CancelKeyPress += (sender, eArgs) => {
Console.WriteLine("Shutting down.");
_quitEvent.Set();
eArgs.Cancel = true;
};
_quitEvent.WaitOne();
但是我想在发生这种情况时很好地处理应用程序的关闭。
通过其他研究,我发现当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();
这可以在ECS中编译并正常运行。但是...我通过AWS ECS控制台单击“停止”按钮,它将停止任务并重新启动新任务。当我查看该已停止任务的日志时,没有关闭日志消息,也没有正常关闭的迹象,什么也没有。看来这只是被强行杀死。
我在这里错过了什么吗?我可以采取哪些其他措施来正常捕获AWS ECS中的停止任务以正常关闭该任务?
答案 0 :(得分:0)
似乎与处理正常关机的.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!");
}
}
}
如果您想自己尝试,请查阅完整的github repo参考。 https://github.com/imran9m/netconsoleapp.git
您应该在容器中看到的样本日志。
等待信号
解散触发
收到的信号正常关闭
Hello World!
注意-要在本地测试SIGTERM信号,您将需要在dotnet CLI上运行kill -SIGTERM {PID}
而不是CTRL + C。