控制Azure Service Bus队列消息接收

时间:2020-07-30 10:48:50

标签: azure azure-servicebus-queues

我们有一个分布式体系结构,并且有一个本地系统需要调用。挑战在于系统的容量不可扩展,并且无法同时承担更多的请求负载。我们已经实现了服务总线队列,其中有一个消息处理程序正在侦听此队列并调用本机系统。当前的挑战是,每当一条消息发布到队列中时,消息处理程序就会立即处理该请求。但是,我们希望有一个方案,一次只能处理两个请求。选择两个,对其进行处理,然后继续进行下两个。服务总线队列是否提供内置选项来控制此操作,还是我们只能使用自定义逻辑?

var options = new MessageHandlerOptions()
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false
            
            };
        client.RegisterMessageHandler(
            async (message, cancellationToken) =>
            {
                try
                {
                    //Handler to process
                    await client.CompleteAsync(message.SystemProperties.LockToken);
                }
                catch
                {
                    await client.AbandonAsync(message.SystemProperties.LockToken);
                }

            }, options);

2 个答案:

答案 0 :(得分:1)

从我的头顶上看,我认为开箱即用不支持这种功能,所以最好的选择就是自己动手做。

我建议您查看ReceiveAsync()方法,该方法可让您接收特定数量的消息(注意:我不认为这可以保证如果您指定要检索2条消息,它将始终得到两个。例如,如果队列中只有一条消息,那么即使您要求两个,它也可能会返回该消息。

您可能会结合使用ReceiveAsync()方法和PeekAsync()方法,在该方法中还可以提供许多您想查看的消息。如果所查看的消息数为2,则您可以致电ReceiveAsync(),以获得更多的两条消息的机会。

另一种方法是查看队列的ManagementClientGetQueueRuntimeInfoAsync()方法,这将为您提供有关队列中消息数量的信息。有了这些信息,您就可以致电前面提到的ReceiveAsync()

但是,请注意,如果您有多个接收方正在侦听同一队列,则无法保证上面的任何内容都能正常工作,因为无法确定这些消息是否被另一个进程接收。

您可能需要采用一种更为复杂的方式来处理此问题并接收一条消息,然后将其保持活动状态(更新锁等),直到获得另一条消息,然后将它们一起处理。

我认为我没有提供太多帮助,但也许至少它会给您一些想法。

答案 1 :(得分:1)

消息处理程序API专为并发而设计。如果您想在任何给定的时间点处理两条消息,那么最大并发数为2的Handler API将是您的答案。如果您需要在任何给定的时间点处理一批两条消息,则不需要此API。相反,您可以使用Mikolaj提供的答案中概述的较低级别的API来构建自己的消息泵。

请谨慎对待重新锁定消息。这不是保证操作,因为它是客户端操作,并且如果有通信网络,当前,经纪人将重置锁定,并且如果您向外扩展,消息将由另一个竞争的消费者再次处理。这就是为什么在您的方案中进行横向扩展可能会成为一个挑战。

关于接收多个消息时,另外一点是关于MessageReceiver的较低级别的API-ReceiveAsync(n)不能保证n消息会被检索。如果绝对必须有n条消息,则需要循环以确保有n条消息。

关于管理客户端和获取队列消息计数的最后一点-强烈建议这样做。管理客户端不适合在运行时频繁使用。相反,它用于偶尔的呼叫,因为这些呼叫非常慢。鉴于您最终可能会遇到一个处理端点,而一次只能约束两个消息(甚至不是每秒),因此这些调用将增加总的处理时间。