Azure 的 QueueClient.ReceiveMessagesAsync returns 没有消息时

Azure's QueueClient.ReceiveMessagesAsync returns when there are no messages

我正在使用 Azure Storage Queues,我注意到我的成本很高,尽管我的队列中没有很多项目。当我分析指标时,我还注意到队列上的高带宽。经过一些调查,我发现我的代码有问题。我使用以下循环:

private async Task ProcessEventsAsync(CancellationToken cancellationToken)
{
  while (!cancellationToken.IsCancellationRequested)
  {
    var messages = await _queueClient.ReceiveMessagesAsync(maxMessages: 10, cancellationToken: cancellationToken).ConfigureAwait(false);
    foreach (var message in messages.Value)
    {
      // Event handling here...
      await _queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt, cancellationToken: CancellationToken.None).ConfigureAwait(false);
    }
  }
}

当队列中没有消息时,QueueClient.ReceiveMessagesAsync 方法似乎也 returns。这导致我的代码不断循环并消耗大量 CPU 和带宽。

我希望此调用会阻塞,直到队列中至少有一条消息为止。文档对此方法有以下描述:

Receives one or more messages from the front of the queue.

这表明它会阻塞,直到至少有一条消息可用。另一种选择是每隔几秒轮询一次队列,但我宁愿不轮询队列。为了获得适当的响应时间,我需要经常进行轮询。

这不是 Storage Queues 的用途。 ReceiveMessagesAsync 只需在您每次调用时向 blob-storage 队列发出 HTTP 请求。

Azure.Storage.Queues SDK 中没有允许它像消息调度程序一样工作的机制。

如果您想要这种行为,您应该查看 Azure Event Hubs。这是它的用途:在集线器上收听,当一条消息可用时,它会在您的服务中触发一个事件并由您处理。

如果您无法使用存储队列,那么我强烈建议在每个循环之间执行 await Task.Delay(5000, token)。这将大大减少您产生的流量,您的成本也会大大降低。