Managing multiple queue/topic clients?

久未见 提交于 2020-05-16 03:42:46

问题


The challenge here is that I'm trying to create a single facade for dealing with queues and topics while maintaining semantics of Send vs. Publish

For example:

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

Send() would send a message to a queue and Publish() would publish a message to a topic. So I would need to have an instance of IQueueClient and ITopicClient to make these happen; I would inject these to my IServiceBus implementation as dependencies and call them accordingly.

The problem is that the QueueClient and TopicClients require that you specify their destinations when you're newing up the clients which prevents me from allowing that as parameters for my IServiceBus implementation.

I could just create a client on at the time the message is being created, but that's super inefficient. I looked around for at least a connection manager that could act as a factory for the clients but MessagingFactory doesn't seem to be in this SDK (Microsoft.Azure.ServiceBus 3.4.0).

So the questions are - Is there some sort of factory out there that I can use that would allow me to create the proper clients on demand with the same efficiency one would gain by reusing the clients? - Is there some sort of override or alternative client object I should be using to achieve this effect? These two clients are really limiting.


回答1:


Since I believe we can assume that instances of QueueClient and TopicClient are thread safe, what you can do is register the resolved IServiceBus concrete class as a singleton in your IoC container.

In the concrete ServiceBus, you can create a cache of previously seen topic and queue clients:

private readonly ConcurrentDictionary<string, ITopicClient> _topicClientCache
    = new ConcurrentDictionary<string, ITopicClient>();
private readonly ConcurrentDictionary<string, IQueueClient> _queueClientCache
    = new ConcurrentDictionary<string, IQueueClient>();

Then in your Publish method

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);
}

And the same applies for your Send implementation - it would check against the _queueClientCache for the destination (queue name), and create it and cache it the first time it sees it.




回答2:


I was finally able to come across someone that had a similar issue. It turns out that they removed the MessagingFactory, but made the connection reusable. Each client has a constructor overload that takes the connection, so I registered the connection as a singleton and inject that instead of the client, and then just create the clients on demand.

see: https://github.com/Azure/azure-service-bus-dotnet/issues/556

My solution looked a little like this (full implementation omitted for brevity)

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
    }
}


来源:https://stackoverflow.com/questions/55546270/managing-multiple-queue-topic-clients

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!