服务总线-单例连接类?

Ron*_*Ron 5 c# azure azureservicebus azure-servicebus-queues

我试图找出从Web-API使用服务总线的最佳实践是什么。

我已经读到重新创建QueueClient,SubscriptionClient等对象是错误的方法,因此我需要重用工厂和客户端。

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

参考

我需要实现一个特殊的类,该类将保持与服务总线的连接,我在考虑一个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);
    }
 }
Run Code Online (Sandbox Code Playgroud)

如您所见,我没有关闭连接(QueueClient.Close()),应该在哪里关闭连接?用Dispose()实现IDisposable?

如果有更好的方法,请与我分享。

此代码来自具有良好工作负载的Web-API(Azure云服务)。

更新资料

我用Dispose()以下方法更新了我的课程:

     public void Dispose()
     {
         if (msgFactory != null)
         {
             msgFactory.Close();
         }

     } 
Run Code Online (Sandbox Code Playgroud)

ppa*_*rno 4

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

  • 我的问题是我使用的方法是否安全?是否会保持 QueueClient 的单个实例打开并且在应用程序运行时不会关闭它?并且存在像这个问题这样的性能问题http://stackoverflow.com/questions/17998291/reusing-connections-in-azure-service-bus/ (2认同)