服务总线 - 单例连接类?

时间:2015-11-04 02:38:45

标签: c# azure azureservicebus azure-servicebus-queues

我正在尝试弄清楚从Web-API使用Service Bus的最佳做法。

我读过重新创建像QueueClient,SubscriptionClient等对象的方法是错误的方法,所以我需要重用工厂和客户端。

  

Service Bus客户端对象(如Microsoft.ServiceBus.Messaging.QueueClient或Microsoft.ServiceBus.Messaging.MessageSender)是通过MessagingFactory对象创建的,该对象还提供连接的内部管理。发送消息后,不应关闭消息传递工厂或队列,主题和订阅客户端,然后在发送下一条消息时重新创建它们。关闭消息传递工厂将删除与Service Bus服务的连接,并在重新创建工厂时建立新连接。建立连接是一项昂贵的操作,可以通过为多个操作重复使用相同的工厂和客户端对象来避免这种操作。

reference

我需要实现一个特殊的类来保存与Service Bus的连接,我正在考虑一个将保存特定操作的Singleton类(函数如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();
         }

     } 

1 个答案:

答案 0 :(得分:3)

Service Bus SDK使用的默认底层协议是专有的SBMP(服务总线消息传递协议),它在关闭工厂时关闭的TCP / IP连接之上工作。 如果选择使用TransportType = Amqp(在连接字符串中),则可以切换到AMQP协议。在这种情况下,工厂处理与总线的唯一TCP连接和QueueClient,TopicClient类(从工厂创建)实例化上述TCP连接内的会话和链接。会话和链接是用于在单个TCP连接上进行多路复用的两个AMQP概念。 如果仅关闭QueueClient和TopicClient,则关闭操作仅关闭相关会话和链接,但不关闭关闭工厂对象时关闭的TCP连接。 当然,我不知道SBMP如何在内部工作,因为它是一个专有协议。 但是,在dispose中,您可以关闭工厂和相关的队列/主题对象。 你的问题是什么?