如何浏览 Websphere MQ 消息而不删除它?
Posted
技术标签:
【中文标题】如何浏览 Websphere MQ 消息而不删除它?【英文标题】:How do I browse a Websphere MQ message without removing it? 【发布时间】:2010-11-05 13:42:12 【问题描述】:我正在编写一个 .NET Windows 窗体应用程序,它将向 Websphere MQ 队列发布消息,然后轮询另一个队列以获取响应。如果返回响应,应用程序将实时处理部分响应。但是响应需要保留在队列中,以便每日批处理作业(也从响应队列中读取)可以完成其余的处理。
我已经阅读了该消息。我一直想不通的是如何在不删除它的情况下阅读它。
这是我到目前为止所得到的。我是 MQ 新手,所以任何建议都将不胜感激。并随时使用 C# 进行响应。
Public Function GetMessage(ByVal msgID As String) As MQMessage
Dim q = ConnectToResponseQueue()
Dim msg As New MQMessage()
Dim getOpts As New MQGetMessageOptions()
Dim runThru = Now.AddMilliseconds(CInt(ConfigurationManager.AppSettings("responseTimeoutMS")))
System.Threading.Thread.Sleep(1000) 'Wait for one second before checking for the first response'
While True
Try
q.Get(msg, getOpts)
Return msg
Catch ex As MQException When ex.Reason = MQC.MQRC_NO_MSG_AVAILABLE
If Now > runThru Then Throw ex
System.Threading.Thread.Sleep(3000)
Finally
q.Close()
End Try
End While
Return Nothing 'Should never reach here'
End Function
注意:我尚未验证我的代码是否确实删除了该消息。但这就是我理解 MQ 工作的方式,这似乎就是正在发生的事情。如果这不是默认行为,请纠正我。
【问题讨论】:
+1 - 我希望在自己弄清楚之前发现这个问题。 【参考方案1】:您需要使用 MQOO_BROWSE 选项打开队列。然后在您第一次阅读时,您使用 MQGMO_BROWSE_FIRST 选项执行 GET。最后,您后续的 GET 应该使用 MQGMO_BROWSE_NEXT 选项。
注意:MQOO 是 MQ 开放选项,MQGMO 是 MQ 获取消息选项。
【讨论】:
出色的答案。这救了我今天的培根。谢谢。【参考方案2】:您确实应该使用单独的队列来执行此操作。日终处理应该有自己的队列。处理完您的部分消息后,将其发送到 EOD 队列。
使用“浏览”选项,您将不得不跟踪您已经在某处处理过哪些消息。
此外,您可以在 GET 上设置等待超时。所以你不需要“在检查队列之前等待 1 秒”。正如现在所写的那样,您无法达到 no msg available 条件,因为您没有在获取消息选项中设置 NOWAIT。
【讨论】:
+1 好点。我没有在我的帖子中提到我一次只做一个请求和响应。响应的相关 ID 将与请求的消息 ID 匹配,因此跟踪我已经处理的消息应该不是问题。至于等待超时,我已经看到了,但还没有弄清楚如何处理它。我根据您的建议进行了更多研究,并使用该方法大幅清理了该方法。非常感谢!【参考方案3】:为了后代,这里是(我认为)基于 mamboking 和 jmucchiello 答案的方法的改进版本。
Public Function GetMessage(ByVal correlID As Byte()) As MQMessage
Dim waitInterval = CInt(ConfigurationManager.AppSettings("responseTimeoutMS"))
Dim q As MQQueue = Nothing
Try
Dim msg As New MQMessage()
Dim getOpts As New MQGetMessageOptions()
q = ConnectToResponseQueue()
msg.MessageId = MQC.MQMI_NONE
msg.CorrelationId = correlID
getOpts.MatchOptions = MQC.MQMO_MATCH_CORREL_ID
getOpts.WaitInterval = waitInterval
getOpts.Options = MQC.MQGMO_BROWSE_FIRST Or MQC.MQGMO_WAIT
q.Get(msg, getOpts)
Return msg
Finally
If q IsNot Nothing AndAlso q.IsOpen() Then q.Close()
End Try
End Function
【讨论】:
【参考方案4】:我意识到我来这个讨论有点晚了,你可能已经编写了这个应用程序。如果您需要修改它或其他任何可能需要做类似事情的人,我有几点意见。
首先,如果您可以使用 v7 QMgr 和 v7 WMQ 客户端执行此操作,这将是首选解决方案。在 v7 中,.Net 支持已从 SupportPac 移至基础产品的一部分。有相当多的新功能,一些错误修复和更好的性能。此外,在 v7 上,您可以使用 pub-sub...这让我想到了第二个观察结果。
根据原始帖子中的描述,我会在 Pub-Sub 中完成此操作。放置消息的应用程序只需要放置一个,它甚至不需要知道它正在放置一个主题。实际上,您可以为主题设置别名,使其看起来像消息生产者的队列。然后,您的消费应用程序可以订阅,或者您可以进行两个管理订阅,以便发布的消息进入您指定的两个队列。然后,您的应用程序每个都有一个专用队列,并且生产者和批处理应用程序不涉及任何编码更改,这只是配置。当然,驱动事务的应用程序需要实际使用消息而不是浏览它们。
这里有几个优点:
当队列填满消息时,索引会被刷新到磁盘并且超过阈值时,您会看到性能下降,这可能很严重。因此,当前的方法并不能很好地扩展。 使用 pub-sub 方法,您可以拥有实时或批处理应用程序或两者的多个实例,这些实例可以位于相同或不同的 QMgr 上。扩大规模很容易。 您消除了需要在同一个 QMgr 上的实时应用和批处理应用之间的依赖关系。 更透明的管理。如果您看到消息在实时队列中堆积,您就知道您遇到了问题。这里还有几个完全不同的问题。其中之一是使用 Fail if Quiescing 选项。这样做的目的是,当 QMgr 完全关闭时,此选项会导致您的 API 调用以指示 QMgr 正在关闭的返回码结束。如果您不包含此选项,则可能有两个或多个连接的应用程序,QMgr永远完全关闭,需要强制关闭或用蛮力杀死其进程。作为一项规则,始终在所有支持它的 API 调用上使用 Fail if Quiescing。它存在的原因是那些需要 XA 事务性但由于某种原因不能使用它的人。在这种情况下,CONNECT 和第一个 GET 或 PUT 调用使用 Fail if Quiescing set 和后续 GET 或 PUT 操作没有。这会导致 QMgr 等待整个 GET/PUT 调用集完成,然后下一个 CONNECT 或 GET/PUT 使用 Fail if Quiescing,因此 QMgr 有机会在必要时关闭。
这里的另一个观察是这里的代码中没有 Catch。我猜在调用堆栈的范围内还有一个?始终建议从异常中打印 WMQ 返回代码,以便您可以追踪根本原因。在咨询业务中,我总是建议客户未能打印返回代码(或 JMS/XMS 代码的链接异常)是一个阻碍将应用程序推广到生产环境的障碍。这真的很重要。即使您在调用 getMessage() 的代码中遇到了问题,但在此处重用示例代码 sn-p 的人可能不会意识到缺少这一重要部分。
【讨论】:
【参考方案5】:供阅读:
AccessQueue 选项:MQOO_BROWSE 和 MQGetMessageOptions:MQGMO_BROWSE_NEXT
【讨论】:
最高投票和接受的答案已经说明了您所说的并提供了更多详细信息,为什么要发布部分答案作为您自己的答案?以上是关于如何浏览 Websphere MQ 消息而不删除它?的主要内容,如果未能解决你的问题,请参考以下文章