简体   繁体   English

重用Azure Service Bus中的连接

[英]Reusing Connections in Azure Service Bus

We have an API hosted on Windows Azure in a web role with 2 instances that takes in requests, validates them then adds them to an Azure Service Bus Queue. 我们在Windows Azure上以Web角色托管了一个API,其中有2个实例接收请求,验证它们然后将它们添加到Azure Service Bus队列。

Recently we've started load testing this and found that our current code throws the below exception: 最近我们开始加载测试,发现我们当前的代码抛出以下异常:

Could not add command to the command queue Exception: Microsoft.ServiceBus.Messaging.QuotaExceededException: The number of maximumallowed connections have been reached or exceeded for Queue Number of active connections: 100, Maximum allowed connections: 100. 无法向命令队列添加命令异常:Microsoft.ServiceBus.Messaging.QuotaExceededException:已达到或超过队列的最大连接数。活动连接数:100,允许的最大连接数:100。

Would the below client code keep a single connection open assuming we maintained a single instance of the class? 假设我们维护了一个类的实例,下面的客户端代码是否会保持单个连接打开? I am trying to ascertain whether the issue is with ServiceBusClient code or our dependency registration initialising a new client for each request. 我试图确定问题是与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
}

As an extension to this; 作为对此的延伸; if the above code does keep an active connection open; 如果上面的代码确实保持活动连接打开; would using the singleton pattern to store an instance of the ServiceBusClient for each instance of the API be dangerous? 将使用单例模式为每个API实例存储ServiceBusClient的实例是危险的吗? Or does the Azure SDK handle closed connections internally? 或者Azure SDK是否在内部处理封闭连接?

From a connection management perspective, following may be helpful: 从连接管理的角度来看,以下可能会有所帮助:

1) A single connection is created for a MessagingFactory instance 1)为MessagingFactory实例创建单个连接

2) You can create as many QueueClient instances from a single MessagingFactory but they will all use the same actual underlying TCP connection, so consider throughput and availability here because more connections can help 2)您可以从单个MessagingFactory创建尽可能多的QueueClient实例,但它们都将使用相同的实际底层TCP连接,因此请考虑吞吐量和可用性,因为更多连接可以帮助

3) We will reconnect the underlying connection for a MessagingFactory in case it is dropped 3)我们将重新连接MessagingFactory的底层连接,以防它被删除

4) From a QueueClient perspective you are creating connections to a particular Queue, consider these links (several of these can exist over a single MessagingFactory connection). 4)从QueueClient角度来看,您正在创建与特定队列的连接,请考虑这些链接(其中一些链接可以存在于单个MessagingFactory连接上)。 Again if the connection is dropped it will be recreated and so will be the links for the Queues, you do not need to recreate the objects 再次,如果连接被删除,它将被重新创建,因此将是队列的链接,您不需要重新创建对象

5) The Quota of 100 concurrent connections is imposed on a per Queue basis so essentially you can have up to 100 links to a single Queue 5)每个队列强加100个并发连接的配额,所以基本上你可以有多达100个链接到一个队列

6) These are not impacted by how many MessagingFactory instances you create these links over 6)这些不受您创建这些链接的MessagingFactory实例的影响

7) If you call close/dispose on the MessagingFactory then all the links over that connection will be closed too and will not reconnect 7)如果你在MessagingFactory上调用close / dispose,那么该连接上的所有链接也将被关闭,不会重新连接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM