繁体   English   中英

如何正确杀死 ASP.NET Core 应用程序以重新启动 docker 容器

[英]How to propert kill ASP.NET Core application to restart docker container

我有一个在 docker 容器中运行的简单 ASP.NET Core Web API 应用程序。

此应用程序应处理 HTTP 请求并使用来自 Kafka 的事件。 因此,在 Startup.Configure 方法中,我使用无限循环运行专用线程来使用事件。

public void Consume()
{
    Task.Factory.StartNew(async () =>
    {
        try
        {
            while (true)
            {
                var eventMsg = _consumer.Consume();
                await Handle(eventMsg);
            }
        }
        catch (Exception ex)
        {
            _consumer.Close();
                    // log error
            throw;
        }
    }, TaskCreationOptions.LongRunning);
}

然后在启动

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseAuthentication();
            app.UseMvc();

            var consumer = app.ApplicationServices.GetRequiredService<KafkaConsumer>();
            consumer.Consume();
        }

但是当循环中发生错误时,我需要使用应用程序重新启动容器。 在添加throw;时的简单应用程序中throw; 然后它生成未处理的异常,关闭应用程序并在结果容器中重新启动。 但在这种情况下throw; 没有帮助,因为它在后台线程中抛出,我不是在等待结果。 我不是在等待结果,因为当我添加

await consumer.Consume();

它会停止所有应用程序并且 WebAPI 不会运行。

如何以正确的方式处理这个问题? 如果简短,我需要在后台线程中抛出异常然后关闭应用程序以自动重新启动容器。 我无法将Application.Exit添加到Consume方法,因为它是一个库,我无法更改代码。

有没有其他方法可以从后台线程杀死应用程序?

如果我需要在关闭之前添加更多信息,请告诉我。

此应用程序应处理 HTTP 请求并使用来自 Kafka 的事件。 因此,在 Startup.Configure 方法中,我使用无限循环运行专用线程来使用事件。

在 ASP.NET Core 上运行后台服务正确方法是使用托管服务。 所以你的代码看起来像这样:

public class KafkaConsumer : BackgroundService
{
  public KafkaConsumer()
  {
    _consumer = ...;
  }

  protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.Run(async () => 
  {
    try
    {
      while (true)
      {
        var eventMsg = _consumer.Consume();
        await Handle(eventMsg);
      }
    }
    catch (Exception ex)
    {
      _consumer.Close();
      ... // log error
      throw;
    }
  });
}

在您的启动类中注册如下:

public void ConfigureServices(IServiceCollection services)
{
  services.AddHostedService<KafkaConsumer>();
}

但是当循环中发生错误时,我需要使用应用程序重新启动容器。

为此,请注入IHostApplicationLifetime并调用StopApplication

public class KafkaConsumer : BackgroundService
{
  private IHostApplicationLifetime _hostApplicationLifetime;

  public KafkaConsumer(IHostApplicationLifetime hostApplicationLifetime)
  {
    _hostApplicationLifetime = hostApplicationLifetime;
    _consumer = ...;
  }

  protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.Run(async () => 
  {
    try
    {
      while (true)
      {
        var eventMsg = _consumer.Consume();
        await Handle(eventMsg);
      }
    }
    catch (Exception ex)
    {
      _consumer.Close();
      ... // log error
      _hostApplicationLifetime.StopApplication();
      throw;
    }
  });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM