JMS 规定了 3 种确认模式

  • AUTO_ACKNOWLEDGE

  • CLIENT_ACKNOWLEDGE

  • DUPS_OK_ACKNOWLEDGE

Apache ActiveMQ Artemis 支持两种额外的模式:PRE_ACKNOWLEDGEINDIVIDUAL_ACKNOWLEDGE

在某些情况下,您可能能够承受在发生故障时丢失消息,因此在将消息传递给客户端之前在服务器上确认消息是有意义的。

此额外模式由 Apache ActiveMQ Artemis 支持,我们将称之为预确认模式。

在服务器上确认消息之前进行确认的缺点是,如果系统在服务器上确认消息之后消息传递给客户端之前崩溃,消息将丢失。在这种情况下,消息将丢失,并且在系统重启时不会恢复。

根据您的消息传递情况,preAcknowledgement 模式可以避免额外的网络流量和 CPU 资源,但代价是需要处理消息丢失。

预确认模式的一个用例示例是股票价格更新消息。对于这些消息,在发生崩溃时丢失消息可能是合理的,因为下一个价格更新消息很快就会到达,覆盖之前的价格。

请注意,如果您使用预确认模式,那么您将丢失正在消费的消息的事务语义,因为很明显,它们首先是在服务器上进行确认的,而不是在您提交事务时进行确认的。这可能是一种显而易见的事情,但我们希望在这些问题上保持清晰,以避免混淆!

1. 使用 PRE_ACKNOWLEDGE

这可以通过将布尔 URL 参数 preAcknowledge 设置为 true 来配置。

或者,在使用 JMS API 时,使用 ActiveMQSession.PRE_ACKNOWLEDGE 常量创建一个 JMS 会话。

// messages will be acknowledge on the server *before* being delivered to the client
Session session = connection.createSession(false, ActiveMQJMSConstants.PRE_ACKNOWLEDGE);

2. 单个确认

单个确认的一个有效用例是,当您需要拥有自己的调度,并且不知道您的消息处理何时完成时。您应该优先使用每个线程工作者一个消费者的模式,但在某些情况下,这可能不可行,具体取决于您的处理流程的复杂程度。为此,您可以使用单个确认。

您基本上通过使用 ActiveMQJMSConstants.INDIVIDUAL_ACKNOWLEDGE 确认模式创建会话来设置单个 ACK。单个 ACK 继承了客户端确认的所有语义,唯一的例外是消息是单独进行确认的。

请注意,为了避免在 MDB 处理中造成混淆,单个 ACKNOWLEDGE 不支持通过 MDB(或入站资源适配器)使用。这是因为您必须在 MDB 中完成消息的处理流程。

3. 示例

请参阅 预确认示例,该示例演示了如何使用 JMS 的预确认模式。