3

我读了这个问题(多线程 JMS 代码:CLIENT_ACKNOWLEDGE 或事务处理会话),但我不明白消息使用者中这两种方法有什么区别:

  1. 未处理连接。会话处于CLIENT_ACKNOWLEDGE模式。我们收到多条消息,然后是一条acknowledge()
  2. 连接已处理(不是xa)。会话处于AUTO_ACKNOWLEDGE模式。我们收到多条消息,然后执行一个commit().

这取决于消息提供者的行为吗?

4

2 回答 2

3

如果会话被处理,acknowledgeMode则忽略。这就是为什么在 JMS 2.0 中添加了一个新的单参数createSession(int)以使其更直观的原因。所以没有“自动确认模式下的事务处理”之类的东西。您要么有一个已交易的会话,要么有一个自动确认的会话。Message.acknowledge()事务会话中的调用将被忽略(由 JMS API指定)。

那么有什么区别呢?正如互联网上的多个地方声称的那样(包括此处的其他答案),这与您是否使用一个或多个目的地无关。这取决于会话是仅消费还是消费-生产。如果它是只消费的(你不产生任何消息),那么两种模式都是平等的:调用Message.acknowledge()Session.commit()确认会话中收到的所有消息。即使从多个队列中收到。

消费-生产会话的行为:

  • 客户端确认:MessageProducer.send()方法返回后立即提交发送的消息。客户端消息在Message.acknowledge()被调用时会立即得到确认。这在规范中没有特别提到,但我认为如果代理在 ack 一半的 msgs 后失败,客户端会报告错误,只有一部分消息会保持 acked。这为您提供了至少一次的保证:如果您在进程结束时确认并且您的程序中途失败,则输出消息将产生两次。

  • 事务性:发送的消息被原子地提交,同时确认会话中所有接收到的消息。客户端或代理端的任何故障都不会导致仅生成或确认部分消息。这为您提供了一次性处理保证。它甚至更快:如herehere所述,如果您在一个事务中生成多条消息,则该MessageProducer.send()方法将是异步的,该commit()方法将等待所有发送批量完成。

于 2019-12-13T12:25:08.427 回答
2

我认为仅从一个目的地接收消息时没有太大区别。可以使用 CLIENT_ACKNOWLEDGE 或 Transacted 会话。

但是,当在会话中使用多个目标时,例如从队列接收消息,然后对其进行处理并将处理结果发布到同一会话中的另一个主题,事务处理会话更适合。因此接收和发布消息都将发生在一个事务中。根据消息处理的结果,可以提交或回滚事务。

于 2012-07-06T14:18:12.027 回答