【问题标题】:Service Bus - Singleton Connection Class?服务总线 - 单例连接类?
【发布时间】:2015-11-05 17:17:34
【问题描述】:

我正在尝试找出从 Web-API 使用服务总线的最佳实践。

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

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

reference

我需要实现一个特殊的类来保持与服务总线的连接,我正在考虑一个将保持特定操作的单例类(函数如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();
         }

     } 

【问题讨论】:

  • 当你说“关闭连接”时,是http连接吗?
  • @mecek“关闭连接”是指关闭连接对象(QueueClient、MessageFactory 等)。据我了解,MessageFactory 底层有 TCP 连接。
  • 你应该尽可能地重用连接以获得更好的性能,在每个请求中关闭连接会损害性能,同时并发请求的数量正在增加。
  • 我应该建议首先创建一个性能测试环境,您可以在从服务总线与多个服务通信时测试您的代码。然后你可以根据测试结果改进你的代码。
  • 创建一个特殊的单例类来包装并保存一个 MessagingFactory 的实例是个好主意,因为在参考中建议这样做。

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


【解决方案1】:

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

【讨论】:

  • 我的问题是我使用的方法是否安全;将保持 QueueClient 的单个实例打开并且在应用程序运行时不会关闭它?还有像这个问题stackoverflow.com/questions/17998291/…这样的性能问题
  • 性能问题与打开更多连接有关,但正如 Abhishek Lal(他在今天搬到亚马逊之前曾在 Microsoft 的 Service Bus 团队工作)所说(我也说过)你只能使用一个工厂并实例化一个或多个队列客户端。但是,即使只有一个队列客户端,您也可以拥有始终打开的连接。就像服务总线运行良好。
  • 最终实现了 IDispose 并且一切正常。还是谢谢你:)
  • MessagingFactory 在 Microsoft.Azure.EventHubs 库中不可用。您知道是否有另一种方法可以在创建 eventthub 客户端时尝试重用底层 TCP 连接,因为它不可用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-28
相关资源
最近更新 更多