我读了这个问题(多线程 JMS 代码:CLIENT_ACKNOWLEDGE 或事务处理会话),但我不明白消息使用者中这两种方法有什么区别:
- 未处理连接。会话处于
CLIENT_ACKNOWLEDGE
模式。我们收到多条消息,然后是一条acknowledge()
。 - 连接已处理(不是
xa
)。会话处于AUTO_ACKNOWLEDGE
模式。我们收到多条消息,然后执行一个commit()
.
这取决于消息提供者的行为吗?
我读了这个问题(多线程 JMS 代码:CLIENT_ACKNOWLEDGE 或事务处理会话),但我不明白消息使用者中这两种方法有什么区别:
CLIENT_ACKNOWLEDGE
模式。我们收到多条消息,然后是一条acknowledge()
。xa
)。会话处于AUTO_ACKNOWLEDGE
模式。我们收到多条消息,然后执行一个commit()
.这取决于消息提供者的行为吗?
如果会话被处理,acknowledgeMode
则忽略。这就是为什么在 JMS 2.0 中添加了一个新的单参数createSession(int)
以使其更直观的原因。所以没有“自动确认模式下的事务处理”之类的东西。您要么有一个已交易的会话,要么有一个自动确认的会话。Message.acknowledge()
事务会话中的调用将被忽略(由 JMS API指定)。
那么有什么区别呢?正如互联网上的多个地方声称的那样(包括此处的其他答案),这与您是否使用一个或多个目的地无关。这取决于会话是仅消费还是消费-生产。如果它是只消费的(你不产生任何消息),那么两种模式都是平等的:调用Message.acknowledge()
或Session.commit()
确认会话中收到的所有消息。即使从多个队列中收到。
消费-生产会话的行为:
客户端确认:MessageProducer.send()
方法返回后立即提交发送的消息。客户端消息在Message.acknowledge()
被调用时会立即得到确认。这在规范中没有特别提到,但我认为如果代理在 ack 一半的 msgs 后失败,客户端会报告错误,只有一部分消息会保持 acked。这为您提供了至少一次的保证:如果您在进程结束时确认并且您的程序中途失败,则输出消息将产生两次。
事务性:发送的消息被原子地提交,同时确认会话中所有接收到的消息。客户端或代理端的任何故障都不会导致仅生成或确认部分消息。这为您提供了一次性处理保证。它甚至更快:如here或here所述,如果您在一个事务中生成多条消息,则该MessageProducer.send()
方法将是异步的,该commit()
方法将等待所有发送批量完成。
我认为仅从一个目的地接收消息时没有太大区别。可以使用 CLIENT_ACKNOWLEDGE 或 Transacted 会话。
但是,当在会话中使用多个目标时,例如从队列接收消息,然后对其进行处理并将处理结果发布到同一会话中的另一个主题,事务处理会话更适合。因此接收和发布消息都将发生在一个事务中。根据消息处理的结果,可以提交或回滚事务。