我在 .Net Core 上开发的服务很少,我使用 RabbitMq 在服务之间发送消息。为了接收消息,我构建了从IHostedService
继承的服务,这些服务连接到RabbitMq并使用。您可以在下面找到我的基本信息接收器
public abstract class MessageReceiver<TMessage> : IMessageReceiver<TMessage>
{
private readonly IServiceScopeFactory _scopeFactory;
private Task _executingTask;
private CancellationTokenSource _cts;
public string QueueName { get; private set; }
private readonly IMessageHandler<TMessage> _handler;
public MessageReceiver(IServiceScopeFactory scopeFactory, IMessageHandler<TMessage> handler, string queueName)
{
_scopeFactory = scopeFactory;
QueueName = queueName;
_handler = handler;
}
public virtual async Task ExecuteAsync(CancellationToken cancellationToken)
{
using (var scope = _scopeFactory.CreateScope())
{
var factory = scope.ServiceProvider.GetRequiredService<IConnectionFactory>();
var connection = factory.CreateConnection();
var connectionModel = connection.CreateModel();
connectionModel.QueueDeclare(QueueName, true, false, false, null);
connectionModel.BasicQos(0, 100, false);
var basicProperties = connectionModel.CreateBasicProperties();
basicProperties.Persistent = true;
while (!cancellationToken.IsCancellationRequested)
{
var consumer = new EventingBasicConsumer(connectionModel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
_handler.Handle(body);
};
connectionModel.BasicConsume(QueueName, autoAck: true, consumer: consumer);
await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
}
}
}
public Task StartAsync(CancellationToken cancellationToken)
{
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
_executingTask = ExecuteAsync(_cts.Token);
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (_executingTask == null)
{
return;
}
_cts.Cancel();
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));
cancellationToken.ThrowIfCancellationRequested();
}
正如你可以看到它的泛型,所以我也建立IMessageHandler
实际上已经实现了我们的业务逻辑 - 处理收到的消息
这是消息接收者之一
public class DemoReceiver : MessageReceiver<DemoMessage>
{
public DemoReceiver (IServiceScopeFactory factory, IMessageHandler<DemoMessage> handler) : base(factory, handler, QueueNames.Demo)
{
}
}
更重要的一点 - 应用程序正在 Docker 上运行。所以问题是 - 我只是注意到有时它的stoppes消耗来自队列的消息。所以我在RabbitMq队列仪表板中看到了待处理的消息。我不知道是什么原因导致了这个问题。也许它的IHostedService
只是'睡觉'而且不会跑。你有什么想法吗?