管理多个队列/主题客户端?

时间:2019-04-06 05:47:28

标签: azureservicebus azure-servicebus-topics

这里的挑战是我试图创建一个用于处理队列和主题的单一外观,同时保持SendPublish的语义

例如:

public interface IServiceBus
{
    Task Send<T>(T message, string destination, SendOptions options = null);
    Task Publish<T>(T message, string topic, SendOptions options = null);
}

Send()会将消息发送到队列,而Publish()将消息发布到主题。因此,我需要有一个IQueueClientITopicClient的实例才能使这些发生。我会将它们作为依赖项注入到我的IServiceBus实现中,并相应地调用它们。

问题在于,在更新客户端时,QueueClient和TopicClient要求您指定它们的目的地,这使我无法将其用作我的IServiceBus实现的参数。

我可以在创建消息时创建一个客户端,但这效率极低。我到处寻找至少一个可以充当客户端工厂的连接管理器,但是MessagingFactory似乎不在此SDK(Microsoft.Azure.ServiceBus 3.4.0)中。

所以问题是 -是否有某种我可以使用的工厂,可以让我按需创建适当的客户,而效率却与重用客户所获得的效率相同? -是否应该使用某种替代或替代客户端对象来实现此效果?这两个客户真的很有限。

2 个答案:

答案 0 :(得分:2)

由于我相信我们可以假设QueueClient and TopicClient are thread safe的实例,所以您可以在IoC容器中将解析的3.12.4.3. respondWithNewView(view) If ! IsReadableStreamBYOBRequest(this) is false, throw a TypeError exception. If this.[[associatedReadableByteStreamController]] is undefined, throw a TypeError exception. If Type(view) is not Object, throw a TypeError exception. If view does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception. If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception. Return ? ReadableByteStreamControllerRespondWithNewView(this.[[associatedReadableByteStreamController]], view). 具体类注册为单例。

在具体的ServiceBus中,您可以创建以前见过的主题的缓存并将客户端排队:

IServiceBus

然后使用您的private readonly ConcurrentDictionary<string, ITopicClient> _topicClientCache = new ConcurrentDictionary<string, ITopicClient>(); private readonly ConcurrentDictionary<string, IQueueClient> _queueClientCache = new ConcurrentDictionary<string, IQueueClient>(); 方法

Publish

对于您的public async Task Publish<T>(T message, string destination, ...) { // i.e. destination is the topic if (!_topicClientCache.TryGetValue(destination, out var topicClient)) { topicClient = new TopicClient(_myServiceBusConnectionString, destination); _topicClientCache.TryAdd(destination, topicClient); } ... create and serialize message into azureMessage here await topicClient.SendAsync(azureMessage); } 实现,情况也是如此-它会针对目标位置(队列名称)与Send进行比较,然后创建它并在第一次看到它时对其进行缓存。

答案 1 :(得分:0)

我终于能够遇到遇到类似问题的人。事实证明,他们删除了MessagingFactory,但使连接可重用。每个客户端都有一个接受连接的构造函数重载,因此我将连接注册为一个单例,并注入该连接而不是客户端,然后按需创建客户端。

请参阅:https://github.com/Azure/azure-service-bus-dotnet/issues/556

我的解决方案看起来像这样(为简洁起见,省略了完整的实现)

public class AzureServiceBus : IServiceBus
{
    public AzureServiceBus(ServiceBusConnection connection, string replyTo)
    {
        _connection = connection;
        _replyTo = replyTo;
        _retryPolicy = new RetryExponential(
            TimeSpan.FromSeconds(1),
            TimeSpan.FromMinutes(1),
            10);
    }

    public async Task Send<T>(T message, string destination)
    {
        var client = new QueueClient(_connection, destination, ReceiveMode.PeekLock, _retryPolicy);

        // ... do work
    }

    public async Task Publish<T>(T message, string topic, SendOptions options = null)
    {
        var client = new TopicClient(_connection, topic, _retryPolicy);

        // ... do work
    }
}