多个长时间运行的IHostedSerivces或BackgroundService实现

时间:2018-10-17 13:28:30

标签: asp.net-core multiple-instances background-service asp.net-core-hosted-services

我似乎在这个问题上找不到很多东西。我遇到的问题是我需要运行2个以上长时间运行的后台服务,但是只有第一个注册的服务的ExecuteAsync被执行。我尝试通过BackgroundService实现它,并将代码放入ExecuteAsync中,我尝试直接实现IHostedService,并将长时间运行的代码放入StartAsync中。

我认为问题是返回Task.CompletedTask;从未被调用。 例如我有两个Kafka使用者实现为BackgroundServices 除了主题和OnMessage方法外,代码看起来都相同

protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
    var kafkaEndpoint = _kafkaConfig.Endpoint;

    var kafkaTopic = "PhoenixEventStore";

    var consumerConfig = new Dictionary<string, object>
    {
        { "group.id", "consumer1" },
        { "bootstrap.servers", kafkaEndpoint },
        { "auto.offset.reset", "earliest" }
    };

    using (var consumer = new Consumer<Null, string>(consumerConfig, null, new StringDeserializer(Encoding.UTF8)))
    {
        consumer.OnMessage += (obj, msg) =>
        {
            Log.Information($"Consumer1 Received {msg.Value}");
        };

        consumer.OnPartitionEOF += (_, end) =>
        {
            Log.Information($"Consumer1 Reached end of topic {end.Topic} partition {end.Partition}.");
        };

        consumer.OnError += (_, error) =>
        {
            Log.Error($"Consumer1 Error: {error}");
        };

        consumer.Subscribe(new List<string>() { kafkaTopic });

        while (!stoppingToken.IsCancellationRequested)
        {
            consumer.Poll(TimeSpan.FromSeconds(10));
        }

        //consider setting value that check whether the consumer has stopped polling.
    }
    return Task.CompletedTask;
}

由于两个服务都长时间运行Task.Complete从未被点击。但是,如果我注释掉while循环,则两个服务ExecuteAsync都会被命中,而不仅仅是第一个注册。

我发现一种解决方法似乎可行,但是想知道是否还有其他人可以采用更好的方法。

基本上,我重构代码以使长时间运行的代码在称为StartConsumer的void方法中运行,然后使ExecuteAsync看起来像这样

  protected override Task ExecuteAsync(CancellationToken stoppingToken)
  {
        Task.Run(() => StartConsumer(stoppingToken));
        return Task.CompletedTask;
  }

两个服务都使用

注册
services.AddHostedService<MyHostedService1>
services.AddHostedService<MyHostedService2>

1 个答案:

答案 0 :(得分:0)

我有同样的情况,并且有效。模板是

 protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await Foo()
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message, exception: ex);
            }

            await Task.Delay(timeInMlSeconds);
        }
    }