6

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

     } 
Ron
  • 1,744
  • 6
  • 27
  • 53
  • when you say "closing connection", is it http connection? – mehmet mecek Nov 04 '15 at 10:18
  • 1
    @mecek "closing connection" is referring to closing the object of connection (QueueClient, MessageFactory and etc'). There is TCP connection underlying the MessageFactory as I understand it. – Ron Nov 04 '15 at 10:40
  • you should reuse connections as much as possible for better performance , closing connections in every request is going to harm performance, while number of concurrent requests are increasing. – mehmet mecek Nov 04 '15 at 13:50
  • I should suggest that firstly create a performance testing environment that you can test your code when communicating with multiple services from service bus. Then you can improve your code with respect to test results. – mehmet mecek Nov 04 '15 at 13:58
  • 1
    creating a special singleton class that wraps and keeps an instance of MessagingFactory is good idea, because it is recommended so in reference. – mehmet mecek Nov 04 '15 at 14:01

1 Answers1

4

The default underlying protocol used by the Service Bus SDK is the proprietary SBMP (Service Bus Messaging Protocol) that works on top of a TCP/IP connection that is closed when you close the factory. If you choose to use TransportType=Amqp (in the connection string) you can switch to the AMQP protocol. In that case, the factory handles the unique TCP connection to the bus and the QueueClient, TopicClient classes (created from the factory) instantiate a session and a link inside the above TCP connection. Session and link are two AMQP concepts used to multiplex on the single TCP connection. If you close only QueueClient and TopicClient, the closing operation closes only related session and link but not the TCP connection that is closed when you close the factory object. Of course I don't know how SBMP works internally because it's a proprietary protocol. However, in a dispose you could close factory and related queue/topic objects. What's your problem ?

ppatierno
  • 9,431
  • 1
  • 30
  • 45
  • 2
    My question is whether the approach I am using is safe; will keeping a single instance of the QueueClient open and will not close it while the application run ? And there is a performance issues like this question http://stackoverflow.com/questions/17998291/reusing-connections-in-azure-service-bus/ – Ron Nov 04 '15 at 13:32
  • The performance issue is related to open more connection but as Abhishek Lal (he worked in Microsoft in the Service Bus team before moving to Amazon today) said (and I said too) you can use only one factory and instantiate one or more queue client. However, even if only one queue client you can have an always open connection. It's like Service Bus works well. – ppatierno Nov 05 '15 at 09:01
  • Ended up implemented the IDispose and all works fine. Thank you anyway :) – Ron Nov 17 '15 at 00:42
  • MessagingFactory is not available in the Microsoft.Azure.EventHubs library. Do you know if there is an alternate way I can try to reuse the underlying TCP connection when creating eventhub client since it is not available ? – Tany Jan 25 '18 at 12:08