Azure 服务总线发送吞吐量 .Net SDK
Azure Service Bus Send throughput .Net SDK
我目前正在实现一个库来更快地将消息发送到服务总线队列。观察到的是,如果我使用相同的 ServiceBusClient 并使用相同的发件人发送 Parallel.For 中的消息,吞吐量不会那么高,并且我的网络上传速度没有得到充分利用。当我创建个人客户端并使用它们发送时,吞吐量急剧增加,甚至可以很好地利用我的上传带宽。
我的理解是正确的还是一个单一的客户发件人必须做的?此外,我反对创建多个客户端,因为它会使用大量资源来建立客户端连接。有没有对此有所启发的文章?
有一个吞吐量测试工具,它的代码也创建了多个客户端。
protected override Task OnStartAsync()
{
for (int i = 0; i < this.Settings.SenderCount; i++)
{
this.senders.Add(Task.Run(SendTask));
}
return Task.WhenAll(senders);
}
async Task SendTask()
{
var client = new ServiceBusClient(this.Settings.ConnectionString);
ServiceBusSender sender = client.CreateSender(this.Settings.SendPath);
var payload = new byte[this.Settings.MessageSizeInBytes];
var semaphore = new DynamicSemaphoreSlim(this.Settings.MaxInflightSends.Value);
var done = new SemaphoreSlim(1);
done.Wait();
long totalSends = 0;
https://github.com/Azure-Samples/service-bus-dotnet-messaging-performance
是否有库来管理池中的连接?
- 对于新的 SDK,应用了相同的连接管理原则,即重新创建连接的成本很高。
- 您可以将客户端对象直接连接到总线或通过创建 ServiceBusConnection,可以在客户端之间共享单个连接
这是为了将尽可能多的消息发送到单个队列的场景,然后您可以通过在单独的线程上启动多个 ServiceBusConnection 和客户端对象来增加吞吐量。
Is there a library to manage the connections in a pool?
幕后没有连接池,创建新连接的成本相对较高。对于之前的 SDK,建议尽可能 re-use factories and clients。
有关详细信息,请参阅此 article。
根据您代码中的模式,我假设您使用的是 Azure.Messaging.ServiceBus
包。如果不是这种情况,请忽略此 post.
的其余部分
ServiceBusClient
表示与服务的单个 AMQP 连接。从此客户端生成的任何发送方、接收方和处理方都将共享该连接。这使您的应用程序能够控制使用的连接数并以最适合您的上下文的方式将它们集中在一起。
建议在应用程序的生命周期内重复使用客户端、发送方、接收方和处理器;虽然连接是共享的,但每次产生新的子类型时,它都必须建立一个新的 AMQP link 并执行授权握手 - 这是非常重要的开销。
这些类型在资源方面是自我管理的。对于空闲时间,连接和 links 将被关闭以避免浪费,并且它们将在需要它们的第一个操作时自动重新创建。
关于使用多个客户端、发送方、接收方和处理器 - 这是一种有效的方法,并且在某些情况下可以产生更好的性能。我要提到的一个警告是,在主机环境中使用比 CPU 核心数量更多的客户端会增加导致线程池争用的风险。服务总线库是高度异步的,其性能依赖于及时安排异步调用的延续。
不幸的是,性能调整很难概括,因为它因不同的应用程序和托管环境而异。要找到合适的发送方数量以最大化应用程序的吞吐量,我们建议您花时间测试不同的值并观察特定系统中的性能特征。
我目前正在实现一个库来更快地将消息发送到服务总线队列。观察到的是,如果我使用相同的 ServiceBusClient 并使用相同的发件人发送 Parallel.For 中的消息,吞吐量不会那么高,并且我的网络上传速度没有得到充分利用。当我创建个人客户端并使用它们发送时,吞吐量急剧增加,甚至可以很好地利用我的上传带宽。
我的理解是正确的还是一个单一的客户发件人必须做的?此外,我反对创建多个客户端,因为它会使用大量资源来建立客户端连接。有没有对此有所启发的文章?
有一个吞吐量测试工具,它的代码也创建了多个客户端。
protected override Task OnStartAsync()
{
for (int i = 0; i < this.Settings.SenderCount; i++)
{
this.senders.Add(Task.Run(SendTask));
}
return Task.WhenAll(senders);
}
async Task SendTask()
{
var client = new ServiceBusClient(this.Settings.ConnectionString);
ServiceBusSender sender = client.CreateSender(this.Settings.SendPath);
var payload = new byte[this.Settings.MessageSizeInBytes];
var semaphore = new DynamicSemaphoreSlim(this.Settings.MaxInflightSends.Value);
var done = new SemaphoreSlim(1);
done.Wait();
long totalSends = 0;
https://github.com/Azure-Samples/service-bus-dotnet-messaging-performance
是否有库来管理池中的连接?
- 对于新的 SDK,应用了相同的连接管理原则,即重新创建连接的成本很高。
- 您可以将客户端对象直接连接到总线或通过创建 ServiceBusConnection,可以在客户端之间共享单个连接
这是为了将尽可能多的消息发送到单个队列的场景,然后您可以通过在单独的线程上启动多个 ServiceBusConnection 和客户端对象来增加吞吐量。
Is there a library to manage the connections in a pool?
幕后没有连接池,创建新连接的成本相对较高。对于之前的 SDK,建议尽可能 re-use factories and clients。
有关详细信息,请参阅此 article。
根据您代码中的模式,我假设您使用的是 Azure.Messaging.ServiceBus
包。如果不是这种情况,请忽略此 post.
ServiceBusClient
表示与服务的单个 AMQP 连接。从此客户端生成的任何发送方、接收方和处理方都将共享该连接。这使您的应用程序能够控制使用的连接数并以最适合您的上下文的方式将它们集中在一起。
建议在应用程序的生命周期内重复使用客户端、发送方、接收方和处理器;虽然连接是共享的,但每次产生新的子类型时,它都必须建立一个新的 AMQP link 并执行授权握手 - 这是非常重要的开销。
这些类型在资源方面是自我管理的。对于空闲时间,连接和 links 将被关闭以避免浪费,并且它们将在需要它们的第一个操作时自动重新创建。
关于使用多个客户端、发送方、接收方和处理器 - 这是一种有效的方法,并且在某些情况下可以产生更好的性能。我要提到的一个警告是,在主机环境中使用比 CPU 核心数量更多的客户端会增加导致线程池争用的风险。服务总线库是高度异步的,其性能依赖于及时安排异步调用的延续。
不幸的是,性能调整很难概括,因为它因不同的应用程序和托管环境而异。要找到合适的发送方数量以最大化应用程序的吞吐量,我们建议您花时间测试不同的值并观察特定系统中的性能特征。