【问题标题】:Worker service stops working unexpectedlyWorker 服务意外停止工作
【发布时间】:2020-06-24 08:38:59
【问题描述】:

我有 .NET Core 3+ 工作服务,每 10 秒检查一次“一些东西”。在某一时刻,它“随机”停止了这样做,我不知道为什么。到目前为止它发生了两次并且没有异常日志或类似的东西,所以我只能假设我应该在 ExecuteAsync 中添加一个try-catch,但我的问题是:是否有任何已知问题可能导致类似的行为,其中worker 只是停止执行?

是的,没有请求取消(否则,我想它会记录消息“发件人正在停止”)。

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Sender is starting");
        stoppingToken.Register(() => _logger.LogInformation("Sender is stopping"));

        while (!stoppingToken.IsCancellationRequested)
        {
            await Task.Delay(10000, stoppingToken);

            _logger.LogDebug("Worker running at: {time}", DateTimeOffset.Now);

            if (!stoppingToken.IsCancellationRequested)
                await SendPendingMessages();
        }
    }

    private async Task SendPendingMessages()
    {
        var list = ...

        foreach (var item in list)
        {
            try
            {
                // Do stuff as expected
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
        }
    }
}

【问题讨论】:

    标签: c# .net-core service-worker worker


    【解决方案1】:

    到目前为止它发生了两次并且没有异常日志或类似的东西,所以我只能假设我应该在 ExecuteAsync 中添加一个 try-catch,但我的问题是:是否有任何已知问题可能导致类似工人刚刚停止执行的行为?

    这对我来说绝对是个例外。默认情况下,the BackgroundService implementation will ignore any exceptions thrown from ExecuteAsync。如果从 ExecuteAsync 引发异常,则会将其忽略并且服务会停止运行。

    我总是推荐一个带有日志记录的顶级try/catch,这样你至少知道会发生这种情况:

    受保护的覆盖异步任务 ExecuteAsync(CancellationToken stoppingToken)
    {
      _logger.LogInformation("发送者正在启动");
      尝试
      {
        而(!stoppingToken.IsCancellationRequested)
        {
          等待Task.Delay(10000,stoppingToken);
          _logger.LogDebug("Worker 运行时间:{time}", DateTimeOffset.Now);
          if (!stoppingToken.IsCancellationRequested)
            等待 SendPendingMessages();
        }
      }
      捕获(异常前)当(stoppingToken.IsCancellationRequested)
      {
        _logger.LogInformation("发送者正在停止");
      }
      捕获(异常前)当(!stoppingToken.IsCancellationRequested)
      {
        _logger.LogError(ex, "Sender has error");
      }
    }
    

    在相关说明中,如果您认为这是“关键”后台服务,那么您还想stop the application host when this service stops

    私有只读 ILogger _logger;
    私有只读 IHostApplicationLifetime _hostApplicationLifetime;
    
    公共工作者(ILogger 记录器,IHostApplicationLifetime hostApplicationLifetime)
    {
      _logger = 记录器;
      _hostApplicationLifetime = hostApplicationLifetime;
    }
    
    受保护的覆盖异步任务 ExecuteAsync(CancellationToken stoppingToken)
    {
      _logger.LogInformation("发送者正在启动");
      尝试
      {
        而(!stoppingToken.IsCancellationRequested)
        {
          等待Task.Delay(10000,stoppingToken);
          _logger.LogDebug("Worker 运行时间:{time}", DateTimeOffset.Now);
          if (!stoppingToken.IsCancellationRequested)
            等待 SendPendingMessages();
        }
      }
      捕获(异常前)时(stoppingToken.IsCancellationRequested)
      {
        _logger.LogInformation("发送者正在停止");
      }
      捕获(异常前)当(!stoppingToken.IsCancellationRequested)
      {
        _logger.LogError(ex, "Sender has error");
      }
      最后
      {
        _hostApplicationLifetime.StopApplication();
      }
    }
    

    【讨论】:

      【解决方案2】:

      注意这条线

      await Task.Delay(10000, stoppingToken);
      

      当你触发你的取消令牌时会抛出 OperationCancelledException,它是未处理的。

      还要确保 LogError() LogDebug() 有一个 catch all tr​​y 块并且不能抛出自己,这也会破坏你的代码。

      看不到其他有问题的地方。

      【讨论】:

        猜你喜欢
        • 2020-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-09
        • 1970-01-01
        • 2013-10-05
        • 2017-06-29
        • 1970-01-01
        相关资源
        最近更新 更多