消费者端的CLIENT_ACKNOWLEDGE和Session.commit()有什么区别 - JMS

3
我读了这个问题(Multithreaded JMS code : CLIENT_ACKNOWLEDGE or transacted session),但我不明白在消息消费者中这两种方法的区别是什么:
  1. 连接未被事务化,会话处于CLIENT_ACKNOWLEDGE模式。我们接收多个消息,然后使用acknowledge()进行确认。
  2. 连接已被事务化(非xa),会话处于AUTO_ACKNOWLEDGE模式。我们接收多个消息,然后执行commit()
这是否取决于消息提供程序的行为?
2个回答

3
如果会话被事务化,那么acknowledgeMode将被忽略。这就是为什么在JMS 2.0中添加了一个新的单参数createSession(int)以使其更加直观。所以不存在“自动确认模式下的事务性会话”。你要么有一个事务性会话,要么有一个自动确认会话。在事务性会话中调用Message.acknowledge() 将被忽略(这是由JMS API指定的)。 那么区别在哪里?它不取决于您使用一个还是多个目标,如许多互联网站点所述(包括其他答案)。它取决于会话是仅消费还是消费生成。如果是仅消费(您不生成任何消息),那么两种模式是相等的:调用Message.acknowledge() Session.commit() 都会确认会话中接收到的所有消息。即使从多个队列中接收的消息也是如此。
消费生成会话的行为:
- 客户端确认:发送的消息在MessageProducer.send()方法返回时立即提交。当调用Message.acknowledge() 时,客户端消息将一次性全部确认。这在规范中没有明确说明,但我认为如果代理在确认了一半的消息后失败,客户端将报告错误,并且只有部分消息会保留已确认状态。这给您提供了至少一次的保证:如果在处理过程结束时确认,并且程序在中途失败,则输出消息将被生成两次。 - 事务性:发送的消息原子地提交,同时确认会话中接收到的所有消息。客户端或代理方面的任何故障都不会导致仅生成或确认部分消息。这为您提供了精确一次的处理保证。它甚至更快:正如此处此处所述,如果在一个事务中生成多个消息,则MessageProducer.send()方法将异步执行,而commit()方法将等待所有批处理发送完成。

一旦MessageProducer.send()方法返回,提交就会执行。我认为重要的是要区分同步和异步消息传送。例如ActiveMQ在这里做了一个很好的工作,提供了一般的解释 - https://activemq.apache.org/async-sends - Mikhail2048
@misha2048 我会说ActiveMQ的非标准扩展。我们在这个答案中记录了符合标准的行为。 - Oliv
是的,绝对没问题。 - Mikhail2048

2

我认为当消息只来自一个目的地时,并没有太大的区别。可以使用CLIENT_ACKNOWLEDGE或Transacted session。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接