【问题标题】:Azure ServiceBus Queue. I receive the same message several timesAzure 服务总线队列。我多次收到相同的消息
【发布时间】:2013-07-22 12:08:20
【问题描述】:

我调用了一次client.Send(brokeredMessage);,但我收到了多次消息。对于句柄队列,我使用此代码

private static void HandleQueue(string queueName, MessageHandler messageHandler)
        {
            // Create the queue if it does not exist already
            string connectionString =
                Configuration.GetConnectionString("Microsoft.ServiceBus.ConnectionString",false);

            var namespaceManager =
                NamespaceManager.CreateFromConnectionString(connectionString);

            if (!namespaceManager.QueueExists(queueName))
            {
                namespaceManager.CreateQueue(queueName);
            }

            QueueClient client =
                QueueClient.CreateFromConnectionString(connectionString, queueName);

            while (true)
            {
                BrokeredMessage message = client.Receive();

                if (message != null)
                {
                    try
                    {    
                        messageHandler(message);

                        // Remove message from queue
                        message.Complete();
                    }
                    catch (Exception)
                    {
                        // Indicate a problem, unlock message in queue
                        message.Abandon();
                    }
                }
            }
        }

问题是BrokeredMessage message = client.Receive(); 被多次调用并返回相同的消息,如果messageHandler(message); 的执行需要很长时间。我该如何解决?

【问题讨论】:

    标签: .net azure azure-servicebus-queues


    【解决方案1】:

    消息在您处理时被解锁。设置消息锁定超时的正确位置在QueueDescription http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.queuedescription.lockduration.aspx

    此处允许的最长时间为 5 分钟,因此如果您需要处理更长时间的消息,则可以在消息上调用 RenewLock 以继续使其对其他消费者不可见。您是对的,在您完成处理之前调用Complete 是不可取的,因为如果您处理崩溃,那么您将不会再次收到消息。

    BrokeredMessage.ScheduledEnqueueTimeUtc 的上述属性用于在消息从队列中显示给消费者时“延迟”。假设您在第 1 天发送消息并将预定时间设置为第 2 天,那么直到第 2 天,Recieve 调用才会返回消息。

    【讨论】:

    • 5分钟后,如果尝试更新锁,它会显示锁已过期消息!
    • 锁定期限到期后我不能更新锁定吗?例如5分钟后如果尝试更新锁定,它会显示锁定已过期消息!
    • @Rusty:你需要更新锁过期之前。如果锁在 5 分钟后到期,请提前 10 秒更新。您可以重复续订。
    【解决方案2】:

    你应该做几件事:

    1. 在您的 While(true) 循环中引入睡眠时间。比方说,Thread.Sleep(30000);
    2. 检索消息内容并将消息标记为完成。然后将检索到的内容传递给您的消息处理程序,而不是消息本身。等待“messagehanfler”完成不是一个好习惯。
    3. 如果在处理过程中消息处理程序内部发生错误,请将另一条具有相同内容的代理消息加入队列。
    4. 处理有害消息。检查每条代理消息的传递计数,如果传递计数超过 n 次(比如 5 次),则删除该消息。

    希望对你有帮助!

    【讨论】:

    • 我不认为 1 分是个好主意。在 messageHandler(message) 之前执行 message.Complete() 可以提供帮助,但它并不能解决多次 deleviering 的问题。在我的情况下,如果您的意思是交付计数是对象类型 BrokeredMessage 的属性,它始终等于 1。
    【解决方案3】:

    如果消息在允许的时间内没有得到处理,听起来你的消息会返回队列(根据你的描述,它只在 messageHandler 运行很长时间时才会发生)。

    听起来您想增加消息的可见性超时,这样它们就不会这么快安静地返回队列。对于 ServiceBus,这意味着如果消息尚未完成,则预先计算消息重新出现的时间

    http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.brokeredmessage.scheduledenqueuetimeutc.aspx

    【讨论】:

    • 我可以为 BrokeredMessage.ScheduledEnqueueTimeUtc 设置 DateTime.MaxValue 以避免消息返回队列或以某种方式标记它吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 2017-11-01
    • 1970-01-01
    相关资源
    最近更新 更多