7

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

4

5 回答 5

14

您需要使用 MQOO_BROWSE 选项打开队列。然后在您第一次阅读时,您使用 MQGMO_BROWSE_FIRST 选项执行 GET。最后,您的后续 GET 应该使用 MQGMO_BROWSE_NEXT 选项。

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

于 2009-06-24T16:03:03.647 回答
2

为了子孙后代,这是一个(我认为)基于 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
于 2009-06-24T20:38:43.527 回答
1

您确实应该使用单独的队列来执行此操作。日终处理应该有自己的队列。处理完您的部分消息后,将其发送到 EOD 队列。

使用“浏览”选项,您将不得不跟踪您已经在某处处理过哪些消息。

此外,您可以在 GET 上设置等待超时。所以你不需要“在检查队列之前等待 1 秒”。正如现在所写的那样,您无法达到 no msg available 条件,因为您没有在获取消息选项中设置 NOWAIT。

于 2009-06-24T16:12:29.293 回答
1

我意识到我来这个讨论有点晚了,你可能已经编写了这个应用程序。如果您需要修改它或其他任何可能需要做类似事情的人,我有几点意见。

首先,如果您可以使用 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 如果静默集和后续 GET 或 PUT 操作没有。这会导致 QMgr 等待整个 GET/PUT 调用集完成,但随后下一个 CONNECT 或 GET/PUT 使用 Fail if Quiescing,因此 QMgr 有机会在必要时关闭。

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

于 2010-05-07T06:31:45.813 回答
-1

供阅读:

AccessQueue 选项:MQOO_BROWSE 和 MQGetMessageOptions:MQGMO_BROWSE_NEXT

于 2022-02-07T13:02:32.250 回答