Search code examples
performanceasp.net-coreazureservicebusazure-servicebus-queues

Does QueueClient.CreateFromConnectionString cache internal connection?


I have an HTTP endpoint in an ASP.NET Core app that sends a couple of messages to Azure Service Bus.

Right now, the controller action code does this:

var client = QueueClient.CreateFromConnectionString(this.connectionString, entityPath);
await client.SendAsync(message);

The QueueClient that is created doesn't support Dispose so I'm wondering how long its lifetime should be? I create a new one per HTTP request. Does the QueueClient's CreateFromConnectionString method cache internal connections to the service bus? What is the optimal solution here? I'm asking because I've been receiving TimeoutExceptions from the service bus lately during traffic spikes.


Solution

  • As this official document mentioned about Service Bus client:

    Service Bus client objects, such as QueueClient or MessageSender, are created through a MessagingFactory object, which also provides internal management of connections. You should not close messaging factories or queue, topic, and subscription clients after you send a message, and then re-create them when you send the next message. Closing a messaging factory deletes the connection to the Service Bus service, and a new connection is established when recreating the factory. Establishing a connection is an expensive operation that you can avoid by re-using the same factory and client objects for multiple operations. You can safely use the QueueClient object for sending messages from concurrent asynchronous operations and multiple threads.

    I'm asking because I've been receiving TimeoutExceptions from the service bus lately during traffic spikes.

    As mentioned in the official document about Service Bus messaging TimeoutException:

    A TimeoutException indicates that a user-initiated operation is taking longer than the operation timeout. You should check the value of the ServicePointManager.DefaultConnectionLimit property, as hitting this limit can also cause a TimeoutException.

    I assumed that you could try to increase OperationTimeout and add retry logic as follows to build your QueueClient and reuse this QueueClient object.

    var builder = new ServiceBusConnectionStringBuilder("{ServicesBusConnectionString}")
    {
        OperationTimeout = TimeSpan.FromMinutes(5)
    };
    var messagingFactory = MessagingFactory.CreateFromConnectionString(builder.ToString());
    QueueClient queueClient = messagingFactory.CreateQueueClient("{queueName}");
    queueClient.RetryPolicy = new RetryExponential(
                    TimeSpan.Zero,
                    TimeSpan.FromMinutes(5),
                    2);
    queueClient.SendAsync("{BrokeredMessage}");