C# c中使用依赖注入的RabbitMQ工作队列#
我在“工作队列”场景中使用rabbitmq 例如,我需要一个由5个消费者组成的池(每个消费者都有自己的通道),这样一个进行I/O操作的消费者就不会阻塞同一队列中的其他消费者 例如。 如果我的队列中有: 消息1、消息2、消息3、消息4。(FistConsumerHandler)的每个实例将使用循环(默认rabbitmq行为)从队列中获取1条消息 我面临的问题是,我需要使用依赖项注入来实现这一点 以下是我到目前为止的情况: 在Windows服务启动时(我的使用者托管在Windows服务中): 消费者处理程序:C# c中使用依赖注入的RabbitMQ工作队列#,c#,.net-core,dependency-injection,rabbitmq,asp.net-core-2.0,C#,.net Core,Dependency Injection,Rabbitmq,Asp.net Core 2.0,我在“工作队列”场景中使用rabbitmq 例如,我需要一个由5个消费者组成的池(每个消费者都有自己的通道),这样一个进行I/O操作的消费者就不会阻塞同一队列中的其他消费者 例如。 如果我的队列中有: 消息1、消息2、消息3、消息4。(FistConsumerHandler)的每个实例将使用循环(默认rabbitmq行为)从队列中获取1条消息 我面临的问题是,我需要使用依赖项注入来实现这一点 以下是我到目前为止的情况: 在Windows服务启动时(我的使用者托管在Windows服务中): 消费者
public class FistConsumerHandler : AsyncEventingBasicConsumer
{
private readonly ILogger<FistConsumerHandler> _logger;
private Guid guid = Guid.NewGuid();
public FistConsumerHandler(
IModel channel,
ILogger<FistConsumerHandler> logger) : base(channel)
{
Received += ConsumeMessageAsync;
_logger = logger;
}
private async Task ConsumeMessageAsync(object sender, BasicDeliverEventArgs eventArgs)
{
try
{
// consumer logic to consume the message
}
catch (Exception ex)
{
}
finally
{
Model.Acknowledge(eventArgs);
}
}
}
公共类FistConsumerHandler:AsyncEventingBasicConsumer
{
专用只读ILogger\u记录器;
私有Guid=Guid.NewGuid();
公共财政顾问(
伊莫代尔海峡,
ILogger记录器):底座(通道)
{
已接收+=ConsumeMessageAsync;
_记录器=记录器;
}
专用异步任务ConsumeMessageAsync(对象发送方,BasicDeliverEventArgs eventArgs)
{
尝试
{
//使用消息的使用者逻辑
}
捕获(例外情况除外)
{
}
最后
{
模型确认(eventArgs);
}
}
}
此代码的问题是:
FooEntity
),这是一个获取注入DB上下文(但可以是任何内容)的简化示例:
公共类RabbitMQConsumer
{
专用只读服务器ViceProvider(提供程序);
公共RabbitMQConsumer(IServiceProvider服务提供者)
{
此。_serviceProvider=服务提供商;
}
公共异步任务ConsumeMessageAsync()
{
//使用语句可以确保在完成时关闭作用域,有助于避免内存泄漏
使用(var scope=this.\u serviceProvider.CreateScope())
{
//在范围内获得您的服务
var context=scope.ServiceProvider.GetRequiredService();
//使用dbContext做事
}
}
}
确保在Startup.cs
中将RabbitMQConsumer
注册为单例,而不是瞬态
参考资料:
FooEntity
),这是一个获取注入DB上下文(但可以是任何内容)的简化示例:
公共类RabbitMQConsumer
{
专用只读服务器ViceProvider(提供程序);
公共RabbitMQConsumer(IServiceProvider服务提供者)
{
此。_serviceProvider=服务提供商;
}
公共异步任务ConsumeMessageAsync()
{
//使用语句可以确保在完成时关闭作用域,有助于避免内存泄漏
使用(var scope=this.\u serviceProvider.CreateScope())
{
//在范围内获得您的服务
var context=scope.ServiceProvider.GetRequiredService();
//使用dbContext做事
}
}
}
确保在Startup.cs
中将RabbitMQConsumer
注册为单例,而不是瞬态
参考资料:
using Microsoft.Extensions.DependencyInjection;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
public class StartupBuilder
{
private static IConnection _connection;
private IModel _channel;
public List<ConsumerHandlerItem> _consumerHandlerItems;
public IServiceCollection Services { get; private set; }
public StartupBuilder(IConnection connection)
{
_connection = connection;
_consumerHandlerItems = new List<ConsumerHandlerItem>();
Services = new ServiceCollection();
}
public IServiceProvider Build()
{
_channel = _connection.CreateModel();
Services.InitSerilog();
// Add channel as singleton (this is not correct as I need 1 channel per ConsumerHandler)
Services.AddSingleton(_channel);
// Register the ConsumerHandler to DI
foreach (var item in _consumerHandlerItems)
{
// Add FirstHandler to DI
Type consumerType = item.ConsumerType;
Services.AddSingleton(consumerType);
}
// Finish DI Setup
var serviceProvider = Services.BuildServiceProvider();
// Bind the consumer handler to the channel and queue
foreach (var item in _consumerHandlerItems)
{
var consumerHandler = (AsyncEventingBasicConsumer)serviceProvider.GetRequiredService(item.ConsumerType);
_channel.AssignNewProcessor(item, consumerHandler);
}
return serviceProvider;
}
}
public static class QueuesHelpers
{
public static void AssignNewProcessor(this IModel channel, ConsumerHandlerItem item, AsyncEventingBasicConsumer consumerHandler)
{
channel.ExchangeDeclare(item.Exchange, ExchangeType.Topic, durable: true);
channel.QueueDeclare(item.Queue, true, false, false, null);
channel.QueueBind(item.Queue, item.Exchange, item.Queue, null);
channel.BasicConsume(item.Queue, false, consumerHandler);
}
}
public class FistConsumerHandler : AsyncEventingBasicConsumer
{
private readonly ILogger<FistConsumerHandler> _logger;
private Guid guid = Guid.NewGuid();
public FistConsumerHandler(
IModel channel,
ILogger<FistConsumerHandler> logger) : base(channel)
{
Received += ConsumeMessageAsync;
_logger = logger;
}
private async Task ConsumeMessageAsync(object sender, BasicDeliverEventArgs eventArgs)
{
try
{
// consumer logic to consume the message
}
catch (Exception ex)
{
}
finally
{
Model.Acknowledge(eventArgs);
}
}
}