这里的挑战是我试图创建一个用于处理队列和主题的单一外观,同时保持Send
与Publish
的语义
例如:
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()
将消息发布到主题。因此,我需要有一个IQueueClient
和ITopicClient
的实例才能使这些发生。我会将它们作为依赖项注入到我的IServiceBus
实现中,并相应地调用它们。
问题在于,在更新客户端时,QueueClient和TopicClient要求您指定它们的目的地,这使我无法将其用作我的IServiceBus
实现的参数。
我可以在创建消息时创建一个客户端,但这效率极低。我到处寻找至少一个可以充当客户端工厂的连接管理器,但是MessagingFactory
似乎不在此SDK(Microsoft.Azure.ServiceBus 3.4.0)中。
所以问题是 -是否有某种我可以使用的工厂,可以让我按需创建适当的客户,而效率却与重用客户所获得的效率相同? -是否应该使用某种替代或替代客户端对象来实现此效果?这两个客户真的很有限。
答案 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
}
}