代码之家  ›  专栏  ›  技术社区  ›  John M Gant aman_novice

如何在不删除Websphere MQ消息的情况下浏览该消息?

  •  7
  • John M Gant aman_novice  · 技术社区  · 15 年前

    我正在编写一个.NET Windows窗体应用程序,它将向Websphere MQ队列发送消息,然后轮询其他队列以获得响应。如果返回响应,应用程序将部分实时处理响应。但是响应需要留在队列中,以便每日批处理作业(也从响应队列读取)可以完成其余的处理。

    我已经读到消息了。我一直没能弄清楚的是,如何在不删除它的情况下阅读它。

    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工作的方式,而这似乎就是正在发生的事情。如果这不是默认行为,请纠正我。

    4 回复  |  直到 13 年前
        1
  •  13
  •   mamboking    15 年前

    您需要使用MQOO_浏览选项打开队列。然后在第一次读取时,使用MQGMO_BROWSE_first选项执行GET。最后,后续GET应该使用MQGMO_BROWSE_NEXT选项。

    注意:MQOO是MQ打开选项,MQGMO是MQ获取消息选项。

        2
  •  2
  •   John M Gant aman_novice    15 年前

    为了子孙后代,这里有一个(我认为)基于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
    
        3
  •  1
  •   jmucchiello    15 年前

    使用浏览选项,您必须跟踪您在某处已经处理的消息。

        4
  •  1
  •   T.Rob    14 年前

    我意识到我来参加这个讨论有点晚了,你可能已经编写了这个应用程序。如果你需要修改它,或者其他人可能需要做类似的事情,我有一些观察。

    这里有几个优点:

    • 当队列中充满消息时,索引会被刷新到磁盘上,超过阈值时,您将看到性能受到严重影响。因此,当前的方法不能很好地进行扩展。
    • 您消除了需要在同一QMgr上的实时应用程序和批处理应用程序之间的依赖关系。

    这里还有两个完全不同的问题。其中之一是使用Fail if Quiescing选项。这样做的目的是,当QMgr完全关闭时,此选项会导致API调用结束,返回代码指示QMgr正在关闭。如果不包括此选项,则QMgr可能会在两个或多个连接的应用程序中 从不

    这里的另一个观察是,这里的代码中没有捕获。我猜在调用堆栈的更高范围内有一个?始终建议打印异常的WMQ返回代码,以便跟踪根本原因。在咨询业务中,我总是建议客户,未能打印返回代码(或JMS/XMS代码的链接异常)是一个阻碍应用程序推广到生产的障碍。这真的很重要。即使您在调用getMessage()的代码中有一个陷阱,重用此处的示例代码段的人也可能没有意识到缺少了这一重要部分。