我已经在Net Core中实现了Kafka事件总线作为单例服务。服务本身在Startup.cs中使用Autofac进行配置。该服务具有Listen()
方法:
public void Listen()
{
using(var consumer = new Consumer<Null, string>(_config, null, new StringDeserializer(Encoding.UTF8)))
{
consumer.Subscribe(new string[] { "business-write-topic" });
consumer.OnMessage += (_, msg) =>
{
Console.WriteLine($"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}");
consumer.CommitAsync(msg);
};
while (true)
{
consumer.Poll(100);
}
}
}
我的理解是,为了使此方法在应用程序的生命周期内不断侦听消息,我必须通过某种方式使ServiceProvider与主机关联,然后从Web主机在Program.cs中对其进行调用。服务实例,并调用方法。
我已将我的Program.cs从默认的Net Core 2.1模板配置为以下内容:
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHost(args);
host.Run();
}
public static IWebHost CreateWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
除了可以使用主机之外,我还可以通过某种方式访问服务,我不知道从这里去哪里。我搜索了类似的问题并阅读了官方文档,但似乎无法弄清楚如何访问该服务,以便可以调用Listen()
方法。
这是实现目标的“必修”方法吗?如果是这样,我该如何进行?如果不是-也就是说-如果通常以另一种方式完成这种任务,我该怎么办?
答案 0 :(得分:2)
我建议使用IHostedService。 IHostedService实现注册为单例,并且一直运行到服务器关闭为止。
创建此基类
public abstract class HostedService : IHostedService
{
private Task executingTask;
private CancellationTokenSource cancellationTokenSource;
public Task StartAsync(CancellationToken cancellationToken)
{
this.cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
this.executingTask = this.ExecuteAsync(this.cancellationTokenSource.Token);
return this.executingTask.IsCompleted ? this.executingTask : Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (this.executingTask == null)
{
return;
}
this.cancellationTokenSource.Cancel();
await Task.WhenAny(this.executingTask, Task.Delay(-1, cancellationToken));
}
protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
}
然后创建消费者主机
public class ConsumerHost : HostedService
{
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
using (var consumer = new Consumer<Null, string>(_config, null, new StringDeserializer(Encoding.UTF8)))
{
consumer.Subscribe(new string[] {"business-write-topic"});
consumer.OnMessage += (_, msg) =>
{
Console.WriteLine(
$"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}");
consumer.CommitAsync(msg);
};
while (!cancellationToken.IsCancellationRequested) // will make sure to stop if the application is being shut down!
{
consumer.Poll(100);
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
}
}
}
}
现在在您的启动类中的ConfigureService方法中添加单例
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHostedService, ConsumerHost>();
}
此服务现在将在网络主机完成构建时启动,并在您关闭服务器时停止。无需手动触发它,让虚拟主机为您完成。
答案 1 :(得分:1)
我认为BackgroundService是您所需要的。
public class ListnerBackgroundService : BackgroundService
{
private readonly ListnerService service;
public ListnerBackgroundService(ListnerService service)
{
this.service = service;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
service.Listen();
return Task.CompletedTask;
}
}
并注册:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IHostedService, ListnerBackgroundService>();
...
}