I'm trying to figure out what is the best practice for using Service Bus from a Web-API.
I've read that re-creating objects like QueueClient, SubscriptionClient and etc' is the wrong approach, so I need to reusing factories and clients.
Service Bus client objects, such as Microsoft.ServiceBus.Messaging.QueueClient or Microsoft.ServiceBus.Messaging.MessageSender, are created through a MessagingFactory object, which also provides internal management of connections. You should not close messaging factories or queue, topic, and subscription clients after you send a message, and then re-create them when you send the next message. Closing a messaging factory deletes the connection to the Service Bus service, and a new connection is established when recreating the factory. Establishing a connection is an expensive operation that can be avoided by re-using the same factory and client objects for multiple operations.
reference
I need to implement a special class that will hold the connection to the Service Bus, I was thinking about a Singleton class that will holds specific operation (function like EnqueueJobToArchiveQueue(Job job)
and the Constructor will initialize the QueueClient, MessageFactory and etc' which will be used by the "specific operation function".
My problem is that I need to close the objects (QueueClient.Close()
), When do I need to close the object ?
Here is my class so far:
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);
}
}
As you can see I dont close the connection (QueueClient.Close()
), where should I close the connection ? implement an IDisposable with Dispose() ?
If there is a better approach I appreciate if you could share it with me.
This code is from a Web-API (Azure Cloud Service) with a decent workload.
Update
I've update my class with Dispose()
as follow:
public void Dispose()
{
if (msgFactory != null)
{
msgFactory.Close();
}
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…