【问题标题】:Detect shutdown signal from docker when using Generic Host IHostBuilder使用通用主机 IHostBuilder 时检测来自 docker 的关闭信号
【发布时间】:2020-07-08 20:35:54
【问题描述】:

我有一个默认的通用主机构建器,如下所示:

public static IHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = Host.CreateDefaultBuilder(args);

    builder
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.ClearProviders();
            logging.AddConsole();
            if (hostingContext.HostingEnvironment.IsDevelopment() == true)
                logging.AddDebug();
        })
        .ConfigureHostConfiguration(configurationBuilder =>
        {
            configurationBuilder.AddCommandLine(args);
        })
        .ConfigureAppConfiguration((hostingContext, configApp) =>
        {
            var env = hostingContext.HostingEnvironment;
            Console.WriteLine(env.EnvironmentName);
        })
        .UseConsoleLifetime();

    return builder;
}

public static async Task Main(string[] args)
{
     var host = CreateDefaultBuilder(args)
                        .ConfigureServices((hostContext, services) =>
                        {
                            services.Configure<HostOptions>(option =>
                            {
                                option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
                            });

                            services.AddLogging();

                            services.AddSimpleInjector(container, options =>
                            {
                                // Hooks hosted services into the Generic Host pipeline while resolving them through Simple Injector
                                options.AddHostedService<Worker>();

                                // Allows injection of ILogger & IStringLocalizer dependencies into application components
                                options.AddLogging();
                                // options.AddLocalization();
                            });
                        })
                        .Build()
                        .UseSimpleInjector(container);

     config.Build();
     await host.RunAsync();
}

我正在使用UseConsoleLifetime 和 docker 运行应用程序,它运行,但我似乎无法正常关闭。

我通过 PowerShell 中的 docker stop 命令优雅地向我的应用程序发送停止信号。

但是,与我按 control+C 的控制台应用不同,该应用没有收到此停止命令,并且在 10 秒后被强制终止。

我的问题是:

  1. 如何检测 docker shutdown 命令?
  2. 如何根据我调用的方法注册两种关闭方法(通过控制台或 docker)(有时我可以直接在 Visual Studio 中作为控制台进行调试,而大多数情况下我会通过 docker 使用,但会很高兴为这两种情况自动注册)。

编辑和更新

我看到回复了,谢谢,提坑AppDomain.CurrentDomain.ProcessExit

对于我的工作人员BackgroundService,该接口具有以下功能:

public class Worker : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
             logger.LogInformation("running at: {time} - stoppingToken {stoppingToken}", DateTimeOffset.Now, stoppingToken.IsCancellationRequested);
             await Task.Delay(1000, stoppingToken);
        }
    }
}

每当发送 ctrl+c 时使用UseConsoleLifetime,设置停止令牌。

在docker内使用相同代码(包括UseConsoleLifetime与原代码相同)时,未设置stoppingToken。

请注意,我看不到我有权访问此令牌源以执行取消。

如果我注册到AppDomain.CurrentDomain.ProcessExit,我如何使用它来设置stoppingToken(而不是制作我自己的stopping token 源,虽然可以做到,但如果可能的话想避免)。

【问题讨论】:

  • 你试过this吗?
  • 看起来不错,谢谢,Domain.CurrentDomain.ProcessExit 可以与UseConsoleLifetime() 并行运行,或者以任何特定方式检测是作为控制台运行还是通过 docker 运行以说明任一注册?
  • 不确定,但您也可以尝试订阅System.Console.CancelKeyPress 活动。
  • 您无需注册ProcessExit 或任何其他活动。 UseConsoleLifetime() 监听 Ctrl+C、SIGINT 和 SIGTERM - 它已经监视进程终止。当你运行docker stop 时,SIGTERM 被发送到容器的根进程。这是你的申请还是其他申请?您如何构建和运行主机? .Build().RunAsync() ?还有什么?
  • 您的 BackgroundService 代码是什么样的?当发出终止信号时,会发出通过ExecuteAsyncCancellationToken 信号。你的代码应该监控它并在它被引发时迅速退出

标签: c# docker .net-core


【解决方案1】:

docker stop 向容器中的主进程发送 SIGTERM 信号。要处理此问题并正常关闭,您需要捕获此信号并执行适当的终止代码。 This SO 问题描述了如何附加响应此信号的事件处理程序。

注意,如果不捕获这个信号,docker会在超时(默认10秒)后强行杀死容器。

要同时处理这两个问题,您可以提取运行的任何清理代码以正常关闭函数,并从两个处理程序中调用它。

【讨论】:

  • 感谢 Orphid,一旦该信号被捕获,您是否知道如何设置传递给工作运行函数的 CancellationToken 停止令牌?
猜你喜欢
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
相关资源
最近更新 更多