
(Azure Service Bus服务总线的两大类消息处理方式: 队列Queue和主题Topic)
问题描述
使用Service Bus作为企业消息代理,当有大量的数据堆积再Queue或Topic中时,如何来优化接收端处理消息的能力呢?
详细解释
在接收端(Receover)的代码中,有两个属性与处理消息的能力有关。一是maxConcurrentCalls(最大并发处理数), 二是prefetchCount (预提取消息数)。 在Service Bus的SDK(azure-messaging-servicebus:7.0.0.0)中,他们的描述如下:
maxConcurrentCalls | 接收端所定义的ServiceBusProcessorClient处理的最大并发消息数。 The max concurrent messages that should be processed by the processor. | |
prefetchCount | 接收端要预先提取的消息数 The number of messages to prefetch |
在初始化ServiceBusProcessorClient对象时,可以设置maxConcurrentCalls和prefetchCount的值。如
实验验证
在本次的实验中,如何来验证maxConcurrentCalls值启作用了呢?如何判断prefetchCount是否获取了消息呢?
- 针对maxConcurrentCalls,可以在处理消息的代码中[processMessage(messageProcessor)]打印出当前线程的ID[Thread.currentThread().getId()]。
- 针对prefetchCount,可以从侧面来验证,即获取message的DeliveryCount来判断已经预提取了多少次
本次实验的代码参考Azure Service Bus的快速入门文档所编写,文末包含全部的代码和POM.XML文件。
首先在代码中设置concall和prefetch值。默认情况下为1.本次实验也从1开始,在设定的10秒钟之内查看消费消息的数量。
然后再处理消息的对象中,打印出当前处理消息的次序,消息ID,Delivery次数,处理消息的线程ID。
第一次实验:处理消息的线程号只有一个:21, 在10秒时间中处理23条消息
Hello World! |
第二次实验:处理消息的线程号有5个:21,21,23,24,25, 在10秒时间中处理42条消息
Hello World! |
第三次实验:处理消息的线程号有10个:21,21 ... 30, 在10秒时间中处理46条消息
Hello World! |
三次测试的结论
- 在测试中,由于测试的时长只有10秒,所以无法得出一个合理的maxConcurrentCalls和prefetchCount值。至少maxCouncurrentCalls的值能大幅度提升接收端(Receiver)处理消息的能力。
- 在第三次的的测试中,我们发现Delivery Count的计数变为了1,这是因为在第二次测试中,我们设置的预提取数量为10,每次提取的数量大于了接收端能处理的数量。在10秒钟的测试中,并没有完全处理完所有提取出来的消息,以致于在第三次测试中,这些消息的Delivery次数从0变成了1。
优化建议
预提取可加快消息流程,方法是在应用程序请求消息时及请求消息前,准备好消息用于本地检索。
- 通过ReceiveAndDelete 接收模式,预提取缓存区获取的所有消息在队列中不再可用,仅保留在内存中预提取缓存区,直到应用程序通过 Receive/ReceiveAsync 或 OnMessage/OnMessageAsync API 接收到它们 。 如果在应用程序接收到消息前终止应用程序,这些消息将丢失,且不可恢复。
- 在PeekLock 接收模式下,提取到预提取缓存区的消息将以锁定状态进入缓存区,并且将超时时钟用于锁定计时。 如果预提取缓存区很大,且处理所需时间过长,以致消息锁定在驻留于预提取缓存区,甚至应用程序还在处理消息时就到期,可能出现一些令人困惑的事件要应用程序处理。
如果消息处理需要高度的可靠性,且处理需要大量精力和时间,则建议谨慎使用或者丝毫不用预提取功能。
如果需要较高吞吐量且消息处理通常比较便宜,则预提取会产生显著的吞吐量优势。
需要均衡对队列或订阅配置的最大预提取数和锁定持续时间,以便锁定超时至少超出最大预提取缓存区大小外加一条消息的累积预期消息处理时间。 同时,锁定超时不应过长,防止消息在被意外丢弃后超出其最大 TimeToLive,因此需要消息的锁定在重新传送消息前到期。
附录一:使用Service Bus Explorer工具快速生成大量消息

附录二:测试实例pom.xml内容
附录三:App.java代码
参考资料
Service Bus Explorer:https:///paolosalvatori/ServiceBusExplorer
预提取 Azure 服务总线消息:https://docs.azure.cn/zh-cn/service-bus-messaging/service-bus-prefetch#if-it-is-faster-why-is-prefetch-not-the-default-option
向 Azure 服务总线队列发送消息并从中接收消息 (Java):https://docs.azure.cn/zh-cn/service-bus-messaging/service-bus-java-how-to-use-queues
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!
















