使用通用主机 IHostBuilder 时检测来自 docker 的关闭信号

g18*_*18c 7 c# docker .net-core

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

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();
}
Run Code Online (Sandbox Code Playgroud)

我正在使用UseConsoleLifetimedocker 来运行应用程序,它可以运行,但我似乎无法正常关闭。

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

但是,与我按 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

在 docker 中使用相同的代码(包括UseConsoleLifetime与原样相同的代码)时,不会设置停止令牌。

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

如果我注册AppDomain.CurrentDomain.ProcessExit如何使用它来设置停止令牌(而不是制作我自己的停止令牌源,因为可以完成,希望尽可能避免)。

码头站

Orp*_*hid 5

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

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

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