【问题标题】:Service Bus - Retrieve message from session by sequence number服务总线 - 按序列号从会话中检索消息
【发布时间】:2014-10-23 10:00:14
【问题描述】:

我目前正在尝试从会话中检索特定消息。

为此,我想在 MessageSession 上使用 .Receive(Int64) 我传入 sequence消息的数量。

这是我的代码 -

long msgSequenceNr = 1337;

QueueClient queueClient = QueueClient.CreateFromConnectionString(Constants.ServiceBusConnectionString, Constants.TestQueueEntityName, ReceiveMode.PeekLock);
MessageSession msgSession = queueClient.AcceptMessageSession(Constants.TestSessionId);

var peekedMsg = msgSession.Peek(msgSequenceNr); // <-- Works fine!
var receivedMsg = msgSession.Receive(msgSequenceNr); // <-- MessageNotFoundException

不幸的是,当 Peek 工作正常时,Receive 将导致 MessageNotFoundException。 这是我错过的限制还是有其他方法可以实现。

请注意,会话中可能有多个消息

【问题讨论】:

    标签: session servicebus azure-pack


    【解决方案1】:

    使用 SequenceNumber 接收只能与 Defer 方法结合使用。这就是你将如何实现它:

    1. 已收到消息,但目前无法处理(可能正在等待其他进程完成)。
    2. 将 SequenceNumber 持久保存在某些持久存储(表存储、SQL 数据库...)中
    3. 当您知道可以继续处理时(例如:相关进程已完成),请从您的持久存储中加载所有序列号。
    4. 使用 Receive(int sequenceNumber) 或 ReceiveBatch(int[] sequenceNumbers) 接收和处理您的延迟消息。

    示例应用程序:https://code.msdn.microsoft.com/windowsazure/Brokered-Messaging-ccc4f879#content

    更新:

    形成您的评论,我注意到“取消延迟”延迟消息可能是一种解决方案。这是一些取消延迟消息的示例代码,它将延迟消息复制到新消息,完成延迟消息并将新消息发送回队列中。这使用 TransactionScope 以事务方式完成并重新发送消息,以避免丢失消息的风险:

        var messageId = "12434539828282";
    
        // Send.
        var msg = new BrokeredMessage {SessionId = "user1", MessageId = messageId };
        msg.Properties.Add("Language", "Dutch");
        queue.Send(msg);
    
        // Receive.
        var session = queue.AcceptMessageSession();
        msg = session.Receive();
    
        // Store the sequence number.
        var sequenceNumber = msg.SequenceNumber;
    
        // Defer.
        msg.Defer();
    
        // Change to true to test if the transaction worked.
        var shouldThrow = false;
    
        // Later processing of deferred message.
        msg = session.Receive(sequenceNumber);
    
        try
        {
            using (var ts = new TransactionScope())
            {
                // Create a new message.
                var undeferredMessage = new BrokeredMessage {SessionId = msg.SessionId, MessageId = msg.MessageId};
                foreach (var prop in msg.Properties)
                    undeferredMessage.Properties.Add(prop);
    
                // Complete and send within the same transaction.
                msg.Complete();
                if (shouldThrow)
                    throw new InvalidOperationException("Some error");
                queue.Send(undeferredMessage);
    
                // Complete the transaction.
                ts.Complete();
            }
        }
        catch (Exception ex)
        {
            msg.Abandon();
        }
    
        if (shouldThrow)
        {
            msg = session.Receive(sequenceNumber);
            Console.WriteLine(msg.MessageId + " should match: " + messageId);
        }
        else
        {
            try
            {
                msg = session.Receive(sequenceNumber);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Message not found, transaction worked OK.");
            }
        }
    

    注意:这里我只是复制属性。请注意您可能想要复制正文和任何其他附加信息。

    【讨论】:

    • 延迟的问题是您无法“取消延迟”它们,不幸的是这也是我们的要求。这是否记录在您需要推迟才能使用序列号接收的某个地方?
    • Clemens Vasters 有这篇文章:stackoverflow.com/questions/18211179/… 所以我认为 MSDN 上应该有一些信息。
    • 谢谢,那么我将不得不寻找另一种方法来从会话中检索特定消息!
    • @TomKerkhove “Undefer”代码示例可以作为您的方案的一个选项吗?
    • 初始示例应用程序必须使用旧版本的 ServiceBus API/SDK 位,许多方法和对象不存在(CreateReceiver、MessageReceipt 等)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 2020-10-23
    • 2021-09-22
    • 2016-05-13
    • 2023-01-30
    • 2021-11-14
    • 1970-01-01
    相关资源
    最近更新 更多