我们有一个分布式体系结构,并且有一个本地系统需要调用。挑战在于系统的容量不可扩展,并且无法同时承担更多的请求负载。我们已经实现了服务总线队列,其中有一个消息处理程序正在侦听此队列并调用本机系统。当前的挑战是,每当一条消息发布到队列中时,消息处理程序就会立即处理该请求。但是,我们希望有一个方案,一次只能处理两个请求。选择两个,对其进行处理,然后继续进行下两个。服务总线队列是否提供内置选项来控制此操作,还是我们只能使用自定义逻辑?
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);
答案 0 :(得分:1)
从我的头顶上看,我认为开箱即用不支持这种功能,所以最好的选择就是自己动手做。
我建议您查看ReceiveAsync()
方法,该方法可让您接收特定数量的消息(注意:我不认为这可以保证如果您指定要检索2条消息,它将始终得到两个。例如,如果队列中只有一条消息,那么即使您要求两个,它也可能会返回该消息。
您可能会结合使用ReceiveAsync()
方法和PeekAsync()
方法,在该方法中还可以提供许多您想查看的消息。如果所查看的消息数为2,则您可以致电ReceiveAsync()
,以获得更多的两条消息的机会。
另一种方法是查看队列的ManagementClient
和GetQueueRuntimeInfoAsync()
方法,这将为您提供有关队列中消息数量的信息。有了这些信息,您就可以致电前面提到的ReceiveAsync()
。
但是,请注意,如果您有多个接收方正在侦听同一队列,则无法保证上面的任何内容都能正常工作,因为无法确定这些消息是否被另一个进程接收。
您可能需要采用一种更为复杂的方式来处理此问题并接收一条消息,然后将其保持活动状态(更新锁等),直到获得另一条消息,然后将它们一起处理。
我认为我没有提供太多帮助,但也许至少它会给您一些想法。
答案 1 :(得分:1)
消息处理程序API专为并发而设计。如果您想在任何给定的时间点处理两条消息,那么最大并发数为2的Handler API将是您的答案。如果您需要在任何给定的时间点处理一批两条消息,则不需要此API。相反,您可以使用Mikolaj提供的答案中概述的较低级别的API来构建自己的消息泵。
请谨慎对待重新锁定消息。这不是保证操作,因为它是客户端操作,并且如果有通信网络,当前,经纪人将重置锁定,并且如果您向外扩展,消息将由另一个竞争的消费者再次处理。这就是为什么在您的方案中进行横向扩展可能会成为一个挑战。
关于接收多个消息时,另外一点是关于MessageReceiver
的较低级别的API-ReceiveAsync(n)
不能不保证n
消息会被检索。如果绝对必须有n
条消息,则需要循环以确保有n
条消息。
关于管理客户端和获取队列消息计数的最后一点-强烈建议不这样做。管理客户端不适合在运行时频繁使用。相反,它用于偶尔的呼叫,因为这些呼叫非常慢。鉴于您最终可能会遇到一个处理端点,而一次只能约束两个消息(甚至不是每秒),因此这些调用将增加总的处理时间。