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

时间:2012-11-17 06:44:14

标签: jms ibm-mq

我观察到当队列(破坏性调用)中的msg被回滚后,如果TX被回滚(MDB容器管理的TX),msg将被放回队列(原始队列或后退队列,具体取决于后台计数和阈值)队列的设置)。让我们说如果发生了某些事情(重复网络问题或某些问题),由于TX的回滚失败,那么Msgs就会丢失。

是真的吗?

由于

2 个答案:

答案 0 :(得分:3)

正如我在前面问题的评论中所指出的那样,简短的回答是“不,如果COMMIT失败,WMQ将不会丢失这些消息”,但让我们更详细地看一下。

当客户端通过网络与MQ建立连接时,会发生的事情是MQ启动一个进程,该进程创建到MQ的共享内存连接和到客户端应用程序的套接字连接。保持事务处于打开状态的是共享内存进程,在WMQ术语中称为“通道代理”。

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

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

从应用程序的角度来看,这两种情况看起来都是一样的 - 应用程序调用{​​{1}}并返回2009 COMMIT。但在第一种情况下,消息由于MQRC_CONNECTION_BROKEN而消失,而在第二种情况下,消息可能会再次传递。由于这种模糊性,应用程序必须能够检测并优雅地处理欺骗消息。

现在在声明这是MQ中的缺陷之前,我要指出,当在网络上使用消息传递而不是WebSphere MQ特有的任何事情时,结果的模糊性是固有的。实际上,JMS 1.1 specification直接在4.4.13中说明了这一点:

  

如果客户端在a上工作时发生故障   Session和commit方法返回,客户端无法确定是否   事务已提交或回滚。同样含糊不清   当非事务性发送a之间发生故障时存在   PERSISTENT消息和发送方法的返回。

     

由JMS应用程序来处理这种歧义。在一些   这种情况,这可能会导致客户产生功能上的重复   消息。

     

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

因此,使用同步点可以消除丢失消息的情况,因为任何COMMIT必须后跟GET才能永久删除队列中的消息。根据定义,COMMIT在应用程序看到消息之前无法到达。但是,同步点无法消除重复邮件的可能性,因为如果COMMIT的{​​{1}}失败,应用程序可能会再次看到该邮件。同样,如果COMMIT的{​​{1}}失败,则应用无法知道GET在到达渠道代理之前或之后是否失败,除了重新连接和{{之外别无选择1}}再次发送消息。

如果您实际上遇到“丢失”的消息,可能性是:

  1. 推送应用程序在COMMIT上失败但未放置该邮件的另一个副本。
  2. PUT上的COMMIT ting应用失败,但邮件没有丢失,但实际上在同步点下。在这种情况下,请停止任何孤立的通道以回滚事务。
  3. 除了这两种情况外,WMQ不会丢失该持久消息。

答案 1 :(得分:1)

没有。消息不会丢失。在事务中,仅在成功提交后才从队列中删除消息。如果提交或回滚失败,则会再次出现消息。如果在调用提交或回滚之前应用程序和队列管理器之间的连接中断,WebSphere MQ会自动执行回滚。这可以确保消息不会丢失。