Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
325 views
in Technique[技术] by (71.8m points)

c# - Service Bus - Singleton Connection Class?

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 ?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...