Jms 从Websphere MQ读取消息始终是破坏性的调用

Jms 从Websphere MQ读取消息始终是破坏性的调用,jms,ibm-mq,Jms,Ibm Mq,我观察到,当稍后从队列读取消息(破坏性调用)时,如果TX回滚(MDB容器管理的TX),消息将被放回队列(原始或退出队列,取决于队列的倒计时和阈值设置)。假设由于TX回滚失败而发生某种情况(重复的网络问题或某些问题),则MSG丢失 这是真的吗 谢谢否。邮件不会丢失。在事务中,只有在成功提交后,才会从队列中删除消息。如果提交或回滚失败,消息将重新出现。如果在调用提交或回滚之前应用程序和队列管理器之间的连接中断,WebSphere MQ将自动执行回滚。这确保了消息不会丢失。正如我在前面问题的评论中指出

我观察到,当稍后从队列读取消息(破坏性调用)时,如果TX回滚(MDB容器管理的TX),消息将被放回队列(原始或退出队列,取决于队列的倒计时和阈值设置)。假设由于TX回滚失败而发生某种情况(重复的网络问题或某些问题),则MSG丢失

这是真的吗


谢谢

否。邮件不会丢失。在事务中,只有在成功提交后,才会从队列中删除消息。如果提交或回滚失败,消息将重新出现。如果在调用提交或回滚之前应用程序和队列管理器之间的连接中断,WebSphere MQ将自动执行回滚。这确保了消息不会丢失。

正如我在前面问题的评论中指出的,简短的回答是“不,如果
提交失败,WMQ不会丢失这些消息”,但让我们看一看更详细的内容

当客户机通过网络连接到MQ时,实际上MQ启动了一个进程,创建到MQ的共享内存连接和到客户机应用程序的套接字连接。保持事务打开的是共享内存进程,在WMQ术语中称为“通道代理”

有两种情况下,
COMMIT
从应用程序的角度来看似乎失败了。在第一种情况下,
COMMIT
被传递到通道代理并执行,但由于网络问题,确认永远不会返回到应用程序。从MQ的角度来看,消息并没有“丢失”,因为应用程序故意提交了
GET
调用

第二种情况是网络故障发生在
COMMIT
到达通道代理之前。在这种情况下,
COMMIT
确实失败了,因为应用程序无法恢复事务所在的连接句柄。当通道代理意识到TCP连接失败时,它将退出事务并关闭通道。此过程中的问题是,通道代理可能需要一段时间才能意识到连接已断开。事实上,大多数平台上的默认TCP超时是两小时。根据服务器的TCP设置,事务处理的
GET
可能会在同步点下保存该消息长达两个小时,使其看起来已被使用。这就是强烈建议使用当前级别的QMgr和客户端的原因之一——它们较少依赖TCP,更多地依赖内部通道心跳协议来检测丢失的连接

从应用程序的角度来看,这两种情况似乎是相同的-应用程序调用
COMMIT
并返回2009
MQRC\u连接\u中断
。但在第一种情况下,由于
提交
而导致消息丢失,在第二种情况下,消息可能会再次传递。由于这种模糊性,应用程序必须能够检测并优雅地处理重复消息

现在,在宣布这是MQ中的一个缺陷之前,让我指出,在通过网络使用消息传递时,这种结果的模糊性是固有的,而不是特定于WebSphere MQ的任何东西。事实上,第4.4.13节直接说明了这一点,其中指出:

如果在客户端提交其在服务器上的工作之间发生故障 会话和提交方法返回时,客户端无法确定 事务已提交或回滚。同样的歧义 在非事务性发送之间发生故障时存在 持久消息和发送方法的返回

由JMS应用程序来处理这种模糊性。在某些方面 在某些情况下,这可能会导致客户端生成功能上重复的 信息

由于会话恢复而重新传递的消息不可用 被认为是重复的消息

因此,使用syncpoint可以消除消息丢失的情况,因为任何
GET
后面必须跟一个
COMMIT
,以便从队列中永久删除消息。根据定义,在应用程序看到消息之前,
COMMIT
无法到达。但是,syncpoint无法消除重复消息的可能性,因为如果
GET
COMMIT
失败,应用程序可能会再次看到该消息。类似地,如果
PUT
COMMIT
失败,则应用程序无法知道
COMMIT
在到达通道代理之前或之后是否失败,并且除了重新连接和
PUT
消息之外别无选择

如果您确实遇到“丢失”消息,则可能是:

  • 应用程序在提交时失败,但没有放置消息的另一个副本
  • GET
    ting应用程序在
    COMMIT
    上失败,消息没有丢失,但实际上处于同步点下。在这种情况下,请停止任何孤立通道以回滚事务
  • 除了这两种情况之外,WMQ不会丢失该持久消息