Jakarta ee 有人确切地知道,如果客户端崩溃,哪些JMS消息将在客户端确认模式下重新传递吗?

Jakarta ee 有人确切地知道,如果客户端崩溃,哪些JMS消息将在客户端确认模式下重新传递吗?,jakarta-ee,jms,Jakarta Ee,Jms,该规范说“确认一条已消费的消息自动确认其会话已发送的所有消息的接收”——但我需要知道的是“已发送”的含义 例如,如果我调用consumer.receive()6次,然后在第三条消息上调用.acknowledge-是(a)只确认前3条消息,还是(b)全部确认6条消息 我真的希望这是选项a,也就是说,在你调用acknowledge之后的消息将被重新传递,否则在我有机会坚持并确认消息之前,很难看到你如何防止在我的接收方进程崩溃时丢失消息。但是规范的措辞并不清楚。我得到的印象是,JMS规范的作者考虑了代

该规范说“确认一条已消费的消息自动确认其会话已发送的所有消息的接收”——但我需要知道的是“已发送”的含义

例如,如果我调用consumer.receive()6次,然后在第三条消息上调用.acknowledge-是(a)只确认前3条消息,还是(b)全部确认6条消息

我真的希望这是选项a,也就是说,在你调用acknowledge之后的消息将被重新传递,否则在我有机会坚持并确认消息之前,很难看到你如何防止在我的接收方进程崩溃时丢失消息。但是规范的措辞并不清楚。我得到的印象是,JMS规范的作者考虑了代理失败,但没有花太多时间考虑如何防止客户端失败:o(

谢谢
Ben

根据规范,选项(b)是正确的行为。如果您获得选项(a)并依赖它,则应用程序将无法移植

在下面的解释中,我具体指的是JMS规范版本1.1(2002年4月12日)

当确认方法实际上在会话级别上运行时,从消息对象调用确认方法这一事实会造成一些混乱。因为它是一种消息方法,直观地说,可以在消息流中选择一个点来生成确认,这似乎是正确的

但真正发生的是,消息确认在会话级别驱动提交调用。由于会话一次只能有一个事务处于活动状态,因此每个确认不限定消息流中的一个点,而是一个时间点。确认提交现有工作单元并启动下一个。消息传递ack之前的ed必须包含在ack提交的工作单元中

“交付”一词通常被认为是API调用的完成,它从队列中删除消息并导致程序内存中的填充对象。实际上,消息被认为是在从队列中移除时传递的,而不管它是否对程序产生影响。例如,考虑以下事件序列:

  • 应用程序请求一条消息
  • 请求通过TCP套接字传递给服务器上的进程,该进程充当应用程序的代理
  • 代理针对队列发出GET
  • 消息被锁定在工作单元中并传递给代理进程
  • 代理进程尝试通过TCP套接字将消息传递给调用应用程序。如果此时连接断开,应用程序将不会看到该消息,但JMS提供程序认为该消息已传递。当检测到断开的连接时,工作单元将被取消,消息将被回滚o队列和重新交付计数增加
  • 应用程序接收消息
  • 应用程序确认该消息
  • 代理进程接收提交调用并执行它
  • 在6和8之间有一个窗口,在此期间可以断开TCP套接字。在JMS提供程序端,它无法真正区分这一点和步骤5中的失败。无论哪种方式,消息都会回滚并稍后重新传递。但是在这种情况下,应用程序将看到消息两次。规范在4.4.1中预计会出现这种情况3其中规定:

    如果在客户端提交会话工作和 commit方法返回时,客户端无法确定事务是否已完成 提交或回滚。发生故障时存在相同的歧义 在持久消息的非事务性发送和返回之间 从发送方法

    由JMS应用程序来处理这种模糊性 可能导致客户端产生功能上重复的消息

    由于会话恢复而重新传递的消息不被视为 重复消息


    在您的示例中,您“调用consumer.receive()6次,然后在第3条消息上调用.acknowledge”,并观察到消息4到6已重新传递,可能的解释是a)这六条消息并非都来自同一会话,或者b)行为不符合规范。

    谢谢,这非常有用。这不是我所希望的答案,但我有一种感觉,可能是这样的。那么,acknowledge方法放在消息对象上而不是会话上是否只是一个意外?正如你所说,它确实给人一种相当误导的印象。我仍然有兴趣知道,除了SonicMQ之外,其他许多提供商是否超越/违反了标准,只承认你调用ack()的消息。。。否则,CLIENT_ACKNOWLEDGE的局限性似乎使它对于真正可靠的消息传递毫无用处。实际上,,是否每个人最终都会使用重量级XA事务,或者放弃一次语义,转而在应用程序层实现可靠性?我怀疑确认方法是在消息上的,因为在这些模型中,会话是容器管理的,并且消息是应用程序唯一可用的对象。无法回答关于其他传输提供程序的问题,因为我对特定提供程序的唯一了解是WebSphere MQ。也许其他人会回应。如果您想吸引更多的评论,请不要忘记接受/投票答案。XA及时确定事务边界的范围,而不是在消息流中的某个点,与客户端确认相同。当调用提交时,XA提交之前传递的任何消息都在同一工作单元中。我不会说CLIENT_ACKNOWLEDGE对于可靠的消息传递是无用的,因为它实现了