【发布时间】:2015-11-05 17:17:34
【问题描述】:
我正在尝试找出从 Web-API 使用服务总线的最佳实践。
我了解到重新创建 QueueClient、SubscriptionClient 等对象是错误的方法,因此我需要重用工厂和客户端。
服务总线客户端对象,例如 Microsoft.ServiceBus.Messaging.QueueClient 或 Microsoft.ServiceBus.Messaging.MessageSender,是通过 MessagingFactory 对象创建的,该对象还提供连接的内部管理。您不应在发送消息后关闭消息传递工厂或队列、主题和订阅客户端,然后在发送下一条消息时重新创建它们。关闭消息传递工厂会删除与服务总线服务的连接,并在重新创建工厂时建立新的连接。建立连接是一项代价高昂的操作,可以通过为多个操作重用相同的工厂和客户端对象来避免。
我需要实现一个特殊的类来保持与服务总线的连接,我正在考虑一个将保持特定操作的单例类(函数如EnqueueJobToArchiveQueue(Job job) 和构造函数将初始化 QueueClient、MessageFactory 等'将被“具体操作函数”使用。
我的问题是我需要关闭对象(QueueClient.Close()),我什么时候需要关闭对象?
到目前为止,这是我的课程:
public class ServiceBusHelper
{
private static readonly ServiceBusHelper instance = new ServiceBusHelper();
private static MessagingFactory msgFactory;
private static NamespaceManager namespaceManager;
private const string jobQueueName = "job";
private const string responseTopicName = "jobResult";
private const string archiveQueueName = "jobArchive";
private static QueueClient archiveQueue;
private static QueueClient jobQueue;
private static TopicClient responseTopic;
private ServiceBusHelper()
{
}
static ServiceBusHelper()
{
msgFactory = MessagingFactory.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"]);
namespaceManager = NamespaceManager.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"]);
if (!namespaceManager.QueueExists(jobQueueName))
{
namespaceManager.CreateQueue(jobQueueName);
}
filteringQueue = QueueClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"], jobQueueName);
if (!namespaceManager.QueueExists(archiveQueueName))
{
namespaceManager.CreateQueue(archiveQueueName);
}
archiveQueue = QueueClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"], archiveQueueName);
if (!namespaceManager.TopicExists(responseTopicName))
{
namespaceManager.TopicExists(responseTopicName);
}
responseTopic = TopicClient.CreateFromConnectionString(ConfigurationManager.AppSettings["ServiceBusCS"],responseTopicName);
}
public static ServiceBusHelper Instance
{
get
{
return instance;
}
}
public void EnququeJobToDo(Job job, string corrId)
{
// Compose the message
BrokeredMessage msg = new BrokeredMessage(job);
msg.CorrelationId = corrId;
// Send the message
filteringQueue.Send(msg);
}
}
如您所见,我没有关闭连接 (QueueClient.Close()),我应该在哪里关闭连接?使用 Dispose() 实现 IDisposable ?
如果有更好的方法,请与我分享。
此代码来自具有良好工作负载的 Web-API(Azure 云服务)。
更新
我已经用Dispose() 更新了我的班级,如下所示:
public void Dispose()
{
if (msgFactory != null)
{
msgFactory.Close();
}
}
【问题讨论】:
-
当你说“关闭连接”时,是http连接吗?
-
@mecek“关闭连接”是指关闭连接对象(QueueClient、MessageFactory 等)。据我了解,MessageFactory 底层有 TCP 连接。
-
你应该尽可能地重用连接以获得更好的性能,在每个请求中关闭连接会损害性能,同时并发请求的数量正在增加。
-
我应该建议首先创建一个性能测试环境,您可以在从服务总线与多个服务通信时测试您的代码。然后你可以根据测试结果改进你的代码。
-
创建一个特殊的单例类来包装并保存一个 MessagingFactory 的实例是个好主意,因为在参考中建议这样做。
标签: c# azure azureservicebus azure-servicebus-queues