正常关机时在ServiceBus QueueClient中处理预取的消息

时间:2019-01-24 15:55:14

标签: c# .net azure azureservicebus

我需要创建一个高吞吐量的ServiceBus队列客户端,该客户端每秒可以处理1000条消息。我设法实现这一目标的唯一方法是结合使用ReceiveMode.ReceiveAndDeletePrefetchCount

var client = new QueueClient(connectionString, queueName, ReceiveMode.ReceiveAndDelete);
client.PrefetchCount = 1000;
client.RegisterMessageHandler(ProcessMessagesAsync, new MessageHandlerOptions());
await Task.Delay(10000);   // wait for 10s while some messages are processed
await client.CloseAsync();

可靠性不是很关键,因此如果我的应用程序崩溃,我可以承受丢失消息的负担。但是,我想避免在正常关机期间丢失消息,例如上面的CloseAsync调用。我特别希望避免丢失驻留在本地缓存中的数百条预取消息。有没有办法让客户端等到预取的消息处理完毕后,却停止接收新的消息?

1 个答案:

答案 0 :(得分:0)

我没有找到合适的解决方法。它似乎是QueueClient设计中的固有限制。但是,我发现MessageReceiver提供了same functionality以及消息的批处理完成功能,从而可以可靠地消耗大量消息(大约500 msg / s)。

var messageReceiver = new MessageReceiver(
    connectionString, 
    entityPath, 
    ReceiveMode.PeekLock, 
    prefetchCount: 1000);

var processedLockTokens = new List<string>();

while (true)
{
    var messages = await messageReceiver.ReceiveAsync(maxMessageCount: 1000, operationTimeout: TimeSpan.FromSeconds(5));
    if (messages == null)
        continue;

    try
    {
        foreach (var message in messages)
        {
            // Process message.

            processedLockTokens.Add(message.SystemProperties.LockToken);

            if (isCancellationRequested)
                return;
        }
    }
    finally
    {
        if (processedLockTokens.Any())
        {
            await messageReceiver.CompleteAsync(processedLockTokens);

            processedLockTokens.Clear();
        }
    }
}