【问题标题】:How Peek works in a Partition enabled Service Bus Queue?Peek 如何在启用分区的服务总线队列中工作?
【发布时间】:2021-02-07 04:35:27
【问题描述】:

我从 Microsoft docs 了解到,在第一次 Peek() 操作期间,任何一个可用的消息代理都会响应并发送其最旧的消息。然后在后续的 Peek() 操作中,我们可以遍历分区以查看每条增加序列号的消息。

我的问题是,在第一次 Peek() 操作期间,我会从任何第一个响应的分区中收到一条消息。是否可以保证我可以查看队列中的所有消息?

以更简单的方式,有三个分区: 分区“A”有 10 条消息,序列号从 1 到 10。 分区“B”有 10 条消息,序列号从 11 到 20。 分区“C”有 10 条消息,序列号从 21 到 30。

现在,如果我执行 Peek() 操作,如果分区“B”首先响应,我将得到的第一条消息是序列号为 11 的消息。下一个 peek 操作将查找序列号递增的消息。我不会错过来自分区“A”的消息,它的序列号为 1-10,因为它总是搜索递增的序列号,所以 peek 操作永远无法到达?

更新

QueueClient queueClient = messagingFactory.CreateQueueClient("QueueName", ReceiveMode.PeekLock);
BrokeredMessage message = null;
while (iteration < messageCount)
{
  message = queueClient.Peek(); // According to docs, Peeks the oldest message from any responding broker, and next iterations peek the message with incremented sequence number
  if (message == null)
    break;
  Console.WriteLine(message.SequenceNumber);
  iteration++;
}

上面的sn-p能保证我可以浏览一个分区队列的所有消息吗?

【问题讨论】:

    标签: c# azure azureservicebus azure-servicebus-queues


    【解决方案1】:

    对于分区实体,序列号是相对于分区发布的。

    [...]

    SequenceNumber 值是分配给消息的唯一 64 位整数,因为它被代理接受和存储并用作其内部标识符。对于分区实体,最高 16 位反映分区标识符。 (https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sequencing)

    因此,您无法跨分区比较序列号以查看哪个更旧。

    例如,我刚刚创建了一个分区队列并将一些消息放入两个分区(按顺序):

    1. Partition 1, SequenceNumber 61924494876344321
    2. Partition 2, SequenceNumber 28991922601197569
    3. Partition 1, SequenceNumber 61924494876344322
    4. Partition 1, SequenceNumber 61924494876344323
    5. Partition 2, SequenceNumber 28991922601197570
    

    浏览/查看消息:仅在较旧的 WindowsAzure.ServiceBus 库中可用。 PeekBatch 并不总是返回 MessageCount 属性中指定的消息数。这种行为有两个常见的原因。一个原因是消息集合的聚合大小超过了 256 KB 的最大大小。另一个原因是,如果队列或主题的 EnablePartitioning 属性设置为 true,则分区可能没有足够的消息来完成请求的消息数量。 一般来说,如果一个应用程序想要接收特定数量的消息,它应该重复调用 PeekBatch 直到它获得该数量的消息,或者没有更多消息可以查看。https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-partitioning,已添加重点)

    因此,您应该能够反复调用 Peek / PeekBatch 以最终获取所有消息。至少,如果您使用官方 SDK。

    【讨论】:

    • 第一次Peek操作时,不保证分区中序号最小的消息先被peek吗?如果是这样,我如何浏览队列的所有消息?因为 Peek 方法通过增加序列号来工作。因此,如果我在第一次窥视操作期间收到来自分区 2 的消息(例如,如果分区 2 首先响应),我会在您的示例中错过来自分区 1 的消息吗?
    • 说真的。莫汉的问题是相关的。 QueueClient 是否还跟踪它所在的分区以及尚未访问的分区?例如,如果分区 5 先响应,是否会完成对分区 5 的枚举,然后在其他某个随机分区开始枚举,以此类推,直到访问完所有分区?
    【解决方案2】:

    无法保证返回的消息是所有分区中最旧的消息。

    因此,这取决于哪个消息代理首先响应,并且将显示来自该分区的最旧消息。在您的示例中,没有关于哪个分区首先响应的一般规则,但可以保证首先显示来自该分区的最旧消息。

    如果要按序列号检索消息,请使用重载的 Peek 方法 Peek(Sequencenumber),参见:https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-browsing

    【讨论】:

    • 如果我需要从最低到最高的顺序查看消息怎么办?
    • 如果你知道最低和最高的序列号,这是可行的。如果您不知道这些数字,让我检查一下是否也有可能
    • 从零开始偷看?
    • @Triynko 好吧,这似乎很容易进行有序检索,但它没有提到任何地方,这就是使用这个 Peek(0) 东西的问题:PI 得到一个有序的方式,但也许我仍然无法重现没有的场景
    猜你喜欢
    • 1970-01-01
    • 2022-08-11
    • 2021-12-11
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 2021-11-14
    • 2017-02-25
    • 1970-01-01
    相关资源
    最近更新 更多