对于 Azure ServiceBus DI 使用 AddAzureClients 和 clientFactory 是否优于单例实现?

问题描述 投票:0回答:1

我有两个不同的服务类实现,我们可以从 Web 应用程序中使用它们来与 Azure 服务总线进行通信。 他们都工作。

其中一个是我认为的标准单例服务类,它实例化和处置 ServiceBus 客户端和发送方,并在启动时使用 .net DI 添加为单例。

另一个是我最近使用 AzureAddClients DI 方法来配置 ServiceBus 客户端和发送器作为启动代码的一部分,而不是将该逻辑封装在服务类中。 服务类采用 IAzureCLientFactory 来在需要时触发发送者等的延迟实例化,并允许服务类在需要时确定作用域而不是单例(尽管感觉服务类仍然可以作为单例运行良好?)。

第二种方法似乎是最新的微软文档中推荐的方法,但当我编写第一个实现时,这两种方法都不存在(或者我错过了)。

一种方法相对于另一种方法是否有任何优势/最佳实践原因? 为了清楚起见,下面两种不同方法的代码。

“标准单例方法”

启动代码

 services.AddSingleton<IAIMarkingMessageService>(s => new AIMarkingMessageServiceSingleton(aiMarkingSettings.ServiceBusNamespace, aiMarkingSettings.InitQueueName, aiMarkingSettings.FeedbackQueueName, siteSettings.DefaultManagedIdentityClientId));

服务类别代码/大纲(为简洁起见,删除了一些细节)

public class AIMarkingMessageServiceSingleton : IAIMarkingMessageService, IAsyncDisposable
{
    readonly ServiceBusClient _client;
    readonly ServiceBusSender _initSender;
    readonly ServiceBusSender _feedbackSender;

    public AIMarkingMessageServiceSingleton(string serviceBusNameSpace, string initQueueName, string feedbackQueueName, string userAssignedClientId)
    {
        var clientOptions = new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets };
        _client = new ServiceBusClient($"{serviceBusNameSpace}.servicebus.windows.net", new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId }), clientOptions);
        _initSender = _client.CreateSender(initQueueName);
        _feedbackSender = _client.CreateSender(feedbackQueueName);
    }

    public async Task<string> SendInitSubmissionAsync(long taskId, string requestUID)
    { 
       ...
    }

    public async Task<List<long>> SendInitSubmissionBatchAsync(IEnumerable<(long taskId, string requestUID)> tasksToInit)
    {
         ...
    }

    public async ValueTask DisposeAsync()
    {         
        await _client.DisposeAsync(); // senders and receivers created by this client will also be disposed by this call
        GC.SuppressFinalize(this);
    }
}

“添加AzureClients方法”

启动代码

services.AddAzureClients(clientBuilder =>
{
    // register the clients
    clientBuilder.AddServiceBusClientWithNamespace($"{aiMarkingSettings.ServiceBusNamespace}.servicebus.windows.net")
                 .ConfigureOptions(x => new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpTcp });

    clientBuilder.UseCredential(new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = siteSettings.DefaultManagedIdentityClientId }));

    // register the sub clients (queue senders)
    // init sender
    clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(

        (_, _, provider) => provider.GetService<ServiceBusClient>()
        .CreateSender(aiMarkingSettings.InitQueueName)).WithName(aiMarkingSettings.InitQueueName);
    // feedback sender
    clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
        (_, _, provider) => provider.GetService<ServiceBusClient>()
        .CreateSender(aiMarkingSettings.FeedbackQueueName)).WithName(aiMarkingSettings.FeedbackQueueName);
});

// could/should be singleton rather than scoped?
services.AddScoped<IAIMarkingMessageService, AIMarkingMessageService>();

服务类别代码/概要

public class AIMarkingMessageService : IAIMarkingMessageService
{
    readonly ServiceBusSender _initSender;
    readonly ServiceBusSender _feedbackSender;

    public AIMarkingMessageService(IAzureClientFactory<ServiceBusSender> senderFactory, IOptions<AIMarkingSettings> config )
    {
        var _config = config.Value;
        _initSender = senderFactory.CreateClient(_config.InitQueueName);
        _feedbackSender = senderFactory.CreateClient(_config.FeedbackQueueName);
    }
    
    public async Task<string> SendInitSubmissionAsync(long taskId, string requestUID)
    { 
       ...
    }

    public async Task<List<long>> SendInitSubmissionBatchAsync(IEnumerable<(long taskId, string requestUID)> tasksToInit)
    {
         ...
    }
}
azure dependency-injection azure-web-app-service azureservicebus
1个回答
0
投票

对于此实现,没有理由优先选择其中之一。这取决于对更自然地适合应用程序模式的偏好。

这两种方法是等效的,因为它们都处理重要部分:

  • 有一个

    ServiceBusClient
    实例和每个可重复使用的发送者。

  • ServiceBusClient
    的生命周期由DI管理并妥善处置。

© www.soinside.com 2019 - 2024. All rights reserved.