跳到主要内容

PubSub+ JCSMP API中客户端接收消息的确认

PubSub+ JCSMP API 为通过流接收的保证消息向 PubSub+ 事件代理提供确认。下图显示了应用程序通过流接收的保证消息的确认过程。在此过程中,客户端应用程序还可以为格式错误的消息或无法处理的消息发送负确认(Nack)。

确认接收的保证消息

img

API确认

保证消息窗口大小限制了 API 在必须向事件代理返回确认以表示已收到窗口中的消息之前可以接收的消息数量。在 API 发送此确认后,保证消息窗口将重新打开,以便可以向 API 发送更多消息。

应用程序可以通过更改通过流属性设置的默认确认计时器和阈值参数(参阅重要流(消息消费者)属性)来调整窗口确认。通常不需要更改这些默认值,这将改变流的性能特征。

应用程序确认

可以使用以下两种应用程序确认模式之一来确认消息:

  • 自动确认
  • 客户端确认

要使用的确认模式通过以下列出的流属性之一设置。默认情况下,使用自动确认模式。

以下代码显示了如何为不同 API 执行确认:

ConsumerFlowProperties.setAckMode(String ackMode)

ackMode 的可能值为:

  • JCSMPProperties.SUPPORTED_MESSAGE_ACK_AUTO

  • JCSMPProperties.SUPPORTED_MESSAGE_ACK_CLIENT

自动确认模式

当使用自动确认模式时,API 自动生成应用程序级确认。

对于 JCSMP,确认发送的时间取决于消息是异步接收还是同步接收:

  • 当异步接收时,确认在消息回调完成后发送。
  • 当同步接收时,确认在 receive() 方法期间从 API 的内部队列中移除消息后发送。重要的是要意识到,在控制权返回给应用程序之前(即在 receive() 方法完成后),确认已经发送。

客户端确认模式

当使用客户端确认模式时,客户端必须明确为每个接收到的消息的消息 ID 发送确认。此外,您还可以选择使用负确认。有关详细信息,请参阅特定消息的负确认。

要明确发送客户端确认,请使用 XMLMessage.ackMessage()

避免未确认消息的数量变得过大(例如,10,000 条或更多),因为事件代理的出站消息速率可能开始下降。

特定消息的负确认

如果您已将应用程序配置为客户端确认(参阅客户端确认模式),则可以使用负确认(Nacks)。当您使用 Nacks 时,您可以发送一个结算结果,以告知事件代理从接收保证消息的处理中得到的结果。根据结算结果,事件代理知道如何在其队列上处理该消息。您可以使用以下结算结果:

  • ACCEPTED — 此确认通知事件代理您的客户端应用程序已成功处理保证消息。当事件代理收到此结果时,它将从其队列中移除该消息。
    • 当您调用结果为 ACCEPTED 的结算函数/方法时,这与在客户端确认模式下调用确认函数/方法相同。
  • FAILED — 此负确认通知事件代理您的客户端应用程序未处理该消息。当事件代理收到此负确认时,它将尝试重新投递该消息,同时遵守投递计数限制。
  • REJECTED — 此负确认通知事件代理您的客户端应用程序可以处理该消息,但它未被接受(例如,验证失败)。当事件代理收到此负确认时,它将从其队列中移除该消息,然后如果已配置,则将消息移动到死信队列(DMQ)。

在可以使用 Nacks 之前,您必须在创建流时将 FAILED、REJECTED 或两者都添加为 Nack 类型,以准备流使用负确认。您不需要添加 ACCEPTED 结果,因为它始终可用。如果您尝试使用未添加的结果,您将收到 Required Settlement Outcome Not Supported 错误。

  • Nacks 可能在传输过程中丢失(例如,由于意外的网络问题)。在开发应用程序时,将这一事实作为处理消息的逻辑的一部分。
  • Nacks 在 10.2.1 及更高版本的事件代理上受支持。如果事件代理不支持 Nacks,则在流绑定请求期间指定结果时会发生 InvalidOperationException

使用 JCSMP API 的 Nacks

要使用 JCSMP API 的 Nacks,请执行以下操作:

  • 启用并准备流以使用负确认:ConsumerFlowProperties.addRequiredSettlementOutcomes(Outcome outcometoadd)
  • 您需要添加以下一项或两项:
    • Outcome.FAILED
    • Outcome.REJECTED
    • 不需要设置 Outcome.ACCEPTED,因为它始终受支持。
  • 您可以使用以下方式确认或否定确认:XMLMessage.settle(settlement_outcome)
  • 可能使用的值:
    • Outcome.ACCEPTED
    • Outcome.FAILED
    • Outcome.REJECTED

以下示例代码显示了如何发送 Nacks:

// 已使用 JCSMPProperties.SUPPORTED_MESSAGE_ACK_CLIENT 创建会话
final ConsumerFlowProperties cfp = new ConsumerFlowProperties().setEndpoint(q);

// 添加结算结果 - 不需要添加 Outcome.ACCEPTED,因为它始终包含
// 消费者可以添加多个结果,例如 cfp.addRequiredSettlementOutcomes(Outcome.FAILED, Outcome.REJECTED);
cfp.addRequiredSettlementOutcomes(Outcome.FAILED);

final FlowReceiver flowReceiver = session.createFlow(null, cfp);
BytesXMLMessage msg = flowReceiver.receive(1000);
try {
processMessage(msg);
msg.settle(Outcome.ACCEPTED); // 与 msg.ackMessage() 相同
} catch (Exception e) {
msg.settle(Outcome.FAILED); // 无法处理消息,结算为 FAILED
}

有关更多信息,请参阅 PubSub+ JCSMP 消息传递 API 参考。