ASP.NET Core中如何注入多个同连接字符串不同队列的ServiceBusClient
实现多个不同队列ServiceBus实例注入的方案
注意:连接字符串相同的场景下,无需创建多个
ServiceBusClient实例,该类本身线程安全,复用单实例即可减少不必要的连接开销。
方案1:使用键控服务(适用于ASP.NET Core 8+)
键控服务支持通过不同标识区分同类型的不同实例,是最简便的实现方式:
- 先配置服务总线参数,在
appsettings.json中添加配置:
"ServiceBusSettings": { "ConnectionString": "你的Azure Service Bus连接字符串", "Queues": { "UserEventQueue": "user-event-queue", "CarReservationQueue": "car-reservation-queue" } }
- 创建对应的配置绑定类:
public class ServiceBusSettings { public string ConnectionString { get; set; } public Dictionary<string, string> Queues { get; set; } }
- 注册服务实例,用队列名称作为区分不同实例的键:
// 绑定配置 builder.Services.Configure<ServiceBusSettings>(builder.Configuration.GetSection("ServiceBusSettings")); // 注册共享的ServiceBusClient单例 builder.Services.TryAddSingleton<ServiceBusClient>(sp => { var settings = sp.GetRequiredService<IOptions<ServiceBusSettings>>().Value; return new ServiceBusClient(settings.ConnectionString, new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets }); }); // 注册不同队列的Receiver builder.Services.AddKeyedSingleton<ServiceBusReceiver>("UserEventQueue", (sp, key) => { var client = sp.GetRequiredService<ServiceBusClient>(); var settings = sp.GetRequiredService<IOptions<ServiceBusSettings>>().Value; return client.CreateReceiver(settings.Queues[key.ToString()], new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock }); }); builder.Services.AddKeyedSingleton<ServiceBusReceiver>("CarReservationQueue", (sp, key) => { var client = sp.GetRequiredService<ServiceBusClient>(); var settings = sp.GetRequiredService<IOptions<ServiceBusSettings>>().Value; return client.CreateReceiver(settings.Queues[key.ToString()], new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock }); }); // 注册不同队列的Sender builder.Services.AddKeyedSingleton<ServiceBusSender>("CarReservationQueue", (sp, key) => { var client = sp.GetRequiredService<ServiceBusClient>(); var settings = sp.GetRequiredService<IOptions<ServiceBusSettings>>().Value; return client.CreateSender(settings.Queues[key.ToString()]); });
- 使用时通过
[FromKeyedServices]特性指定要注入的实例:
private readonly ServiceBusSender _serviceBusSender; public CarReservationMessagingService([FromKeyedServices("CarReservationQueue")] ServiceBusSender serviceBusSender) { _serviceBusSender = serviceBusSender ?? throw new ArgumentNullException(nameof(serviceBusSender)); }
方案2:自定义工厂类(适用于所有ASP.NET Core版本)
如果使用低于.NET 8的版本,没有键控服务能力,可以通过自定义工厂类实现实例区分:
- 编写工厂接口和实现类:
public interface IServiceBusFactory { ServiceBusReceiver GetReceiver(string queueKey); ServiceBusSender GetSender(string queueKey); } public class ServiceBusFactory : IServiceBusFactory { private readonly ServiceBusClient _client; private readonly ServiceBusSettings _settings; private readonly ConcurrentDictionary<string, ServiceBusReceiver> _receiverCache = new(); private readonly ConcurrentDictionary<string, ServiceBusSender> _senderCache = new(); public ServiceBusFactory(ServiceBusClient client, IOptions<ServiceBusSettings> settings) { _client = client; _settings = settings.Value; } public ServiceBusReceiver GetReceiver(string queueKey) { return _receiverCache.GetOrAdd(queueKey, key => _client.CreateReceiver(_settings.Queues[key], new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.PeekLock }) ); } public ServiceBusSender GetSender(string queueKey) { return _senderCache.GetOrAdd(queueKey, key => _client.CreateSender(_settings.Queues[key]) ); } }
- 注册服务:
builder.Services.Configure<ServiceBusSettings>(builder.Configuration.GetSection("ServiceBusSettings")); builder.Services.TryAddSingleton<ServiceBusClient>(sp => { var settings = sp.GetRequiredService<IOptions<ServiceBusSettings>>().Value; return new ServiceBusClient(settings.ConnectionString, new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets }); }); builder.Services.TryAddSingleton<IServiceBusFactory, ServiceBusFactory>();
- 使用时注入工厂获取对应实例:
private readonly ServiceBusSender _serviceBusSender; public CarReservationMessagingService(IServiceBusFactory serviceBusFactory) { _serviceBusSender = serviceBusFactory.GetSender("CarReservationQueue") ?? throw new ArgumentNullException(nameof(_serviceBusSender)); }
内容的提问来源于stack exchange,提问作者Aamir
相关产品推荐
相关产品推荐

