4

我们在 Windows Azure 上以 Web 角色托管了一个 API,其中有 2 个实例接收请求,验证它们,然后将它们添加到 Azure 服务总线队列。

最近我们开始对此进行负载测试,发现我们当前的代码抛出了以下异常:

无法将命令添加到命令队列异常:Microsoft.ServiceBus.Messaging.QuotaExceededException:已达到或超过队列活动连接数的最大允许连接数:100,最大允许连接数:100。

假设我们维护了该类的单个实例,下面的客户端代码是否会保持单个连接打开?我试图确定问题出在 ServiceBusClient 代码还是我们的依赖注册为每个请求初始化一个新客户端。

public class ServiceBusClient : IDisposable
{
    #region Constants and Fields

    protected readonly NamespaceManager NamespaceManager;

    private const int DEFAULT_LOCK_DURATION_IN_SECONDS = 300; // 5 minutes 

    private const string SERVICE_BUS_CONNECTION_STRING_KEY 
                            = "service.bus.connection.string";

    private readonly IMessageBodySerializer _messageBodySerializer;

    private readonly MessagingFactory _messagingFactory;

    private readonly QueueClient _queueClient;

    private readonly string _queueName;

    private readonly ISettingsManager _settingsManager;

    #endregion

    #region Constructors and Destructors

    public ServiceBusClient(
        ISettingsManager settingsManager, 
        IMessageBodySerializer messageBodySerializer, s
        tring queueName)
    {
        _settingsManager = settingsManager;
        _messageBodySerializer = messageBodySerializer;

        var connectionString = _settingsManager.GetSetting<string>(
            SERVICE_BUS_CONNECTION_STRING_KEY);

        NamespaceManager = 
            NamespaceManager.CreateFromConnectionString(connectionString);

        _messagingFactory = 
            MessagingFactory.CreateFromConnectionString(connectionString);

        _queueName = queueName;
        _queueClient = GetOrCreateQueue();
    }

    #endregion

    #region Public Methods and Operators

    public virtual void SendMessage(object bodyObject)
    {
        var brokeredMessage = 
            _messageBodySerializer.SerializeMessageBody(bodyObject);

        _queueClient.Send(brokeredMessage);
    }

    public void Dispose()
    {
        _messagingFactory.Close();
    }

    #endregion

    #region Methods

    private QueueClient GetOrCreateQueue()
    {
        QueueDescription queue;

        if (!NamespaceManager.QueueExists(_queueName))
        {
            var queueToCreate = new QueueDescription(_queueName)
            {
                LockDuration = TimeSpan.FromSeconds(
                    DEFAULT_LOCK_DURATION_IN_SECONDS)
            };

            queue = NamespaceManager.CreateQueue(queueToCreate);
        }
        else
        {
            queue = NamespaceManager.GetQueue(_queueName);
        }

        return _messagingFactory.CreateQueueClient(
                        queue.Path, 
                        ReceiveMode.PeekLock);
    }

    #endregion
}

作为对此的扩展;如果上面的代码确实保持活动连接打开;使用单例模式为 API 的每个实例存储一个 ServiceBusClient 实例会很危险吗?还是 Azure SDK 在内部处理关闭的连接?

4

1 回答 1

10

从连接管理的角度来看,以下可能会有所帮助:

1) 为 MessagingFactory 实例创建单个连接

2) 您可以从单个 MessagingFactory 创建尽可能多的 QueueClient 实例,但它们都将使用相同的实际底层 TCP 连接,因此请在此处考虑吞吐量和可用性,因为更多连接会有所帮助

3) 我们将重新连接 MessagingFactory 的底层连接,以防它被丢弃

4) 从 QueueClient 的角度来看,您正在创建到特定队列的连接,请考虑这些链接(其中几个可以存在于单个 MessagingFactory 连接上)。同样,如果连接被删除,它将被重新创建,队列的链接也是如此,您不需要重新创建对象

5) 100 个并发连接的配额是在每个队列的基础上施加的,所以基本上你可以有多达 100 个链接到单个队列

6) 这些不受您创建这些链接的 MessagingFactory 实例数量的影响

7) 如果您在 MessagingFactory 上调用 close/dispose,则该连接上的所有链接也将关闭并且不会重新连接

于 2013-08-02T03:57:06.933 回答