3

我们正在使用 IBM MQ XMS C# 客户端版本 9.0(在 .NET 4.6.2 框架上)与 IBM MQ 一起工作。我只需要知道给定队列上的所有消息,而无需将它们从队列中删除。

我们还为队列设置了消费者。需要消费者和浏览器协同工作。浏览器不应删除消息,但仍需要获取所有消息。


所以我设置了一个像下面这样的 QueueBrowser,但是 queueBrowser.GetEnumerator() 根本没有收到消息。

使用相同的代码,如果创建一个 MessageConsumer 并附加一个侦听器,它将获取发布到队列的消息。因此,仅 QueueBrowser 出现问题。

谁能指出为什么会这样。为什么 queueEnumerator.MoveNext() 总是返回 false,表示队列中没有消息。

       XMSFactoryFactory  xMSFactoryFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);

        // Create WMQ Connection Factory.
        IConnectionFactory  connectionFactory = xMSFactoryFactory.CreateConnectionFactory();

        connectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, "hostname");
        connectionFactory.SetIntProperty(XMSC.WMQ_PORT, portNumber);
        connectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, "channelName");
        connectionFactory.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT);
        connectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "QueueManagerName");

        // Create connection.
        connectionWMQ = connectionFactory.CreateConnection();
        connectionWMQ.ExceptionListener = new ExceptionListener(OnXMSException);

        // Create session
        ISession sessionWMQ = connectionWMQ.CreateSession(false, AcknowledgeMode.AutoAcknowledge);

        IDestination destination = sessionWMQ.CreateQueue("QueueName"); 


       IQueueBrowser  queueBrowser = sessionWMQ.CreateBrowser(destination);

        connectionWMQ.Start();

         Thread thread = new Thread(KeepBrowsingMessaegs);
            thread.Start();

   --end of the method

   private void KeepBrowsingMessaegs()
    {
      IEnumerator queueEnumerator = queueBrowser.GetEnumerator();
        while (!cancellationTokenSource.IsCancellationRequested)
        {

            if (queueEnumerator.MoveNext())
            {
                ITextMessage textMessage = queueEnumerator.Current as ITextMessage;
                if (textMessage != null)
                {
                    System.Diagnostics.Trace.Write(textMessage);
                }
            }
        }
    }
4

2 回答 2

2

OP 在评论中提到以下内容:作为业务案例的一部分,我们让消费者运行以阅读消息,并希望设置浏览器以便我们只获取消息的副本,以便我们可以在单独的应用程序中跟踪它以记录所有收到的消息。

我在下面提供了一些选项。


选项1

不要仅仅为了记录收到的消息而使用单独的应用程序,而是让您的“业务案例”应用程序将消息记录为处理的一部分。


选项 2

设置两个队列,第一个将接收入站消息并由记录消息的应用程序使用,然后将其副本放入第二个队列,该队列将由您的“业务案例”应用程序使用。


选项 3

使用 IBM MQ 发布/订阅功能创建消息的两个副本,其中一个将由记录消息的应用程序使用,另一个将由您的“业务案例”应用程序使用。请注意,这仅复制消息正文,MQ 消息描述符 (MQMD) 是关于消息的元数据(诸如放置时间、放置日期、消息 ID、用户 ID 等内容)将不会被复制。许多应用程序不查看 MQMD,因此这对您来说可能不是问题。

设置如下所示:

为入站消息创建一个QALIAS,此别名将通过指定目标是一个主题对象来指向一个主题字符串:

DEFINE QALIAS(INBOUND.QUEUE) TARGET(INBOUND.TOPIC) TARGTYPE(TOPIC)

定义TOPIC对象:

DEFINE TOPIC(INBOUND.TOPIC) TOPICSTR(INBOUND/TOPIC)

创建两个QLOCAL对象,一个由记录消息的应用程序使用,另一个由您的“业务案例”应用程序使用:

DEFINE QLOCAL(INBOUND.QUEUE.LOGGER)
DEFINE QLOCAL(INBOUND.QUEUE.PROCESSOR)

定义两个管理SUBSCRIPTION对象以将两个队列订阅到主题主题字符串:

DEFINE SUB(INBOUND.QUEUE.LOGGER.SUB) TOPICSTR(INBOUND/TOPIC) DEST(INBOUND.QUEUE.LOGGER)
DEFINE SUB(INBOUND.QUEUE.PROCESSOR.SUB) TOPICSTR(INBOUND/TOPIC) DEST(INBOUND.QUEUE.PROCESSOR)

上述设置的结果是,每条放入调用队列的消息INBOUND.QUEUE都会有一个副本发布到两个队列INBOUND.QUEUE.LOGGER,并且INBOUND.QUEUE.PROCESSOR.


选项 4

您可以设置三个QLOCAL对象,一个是入站消息的队列,您将有一个程序从该队列中读取,然后将消息的副本写入其他两个队列。Capitalware 维护了一个名为Message Multiplexer (MMX)的开源工具,它可以从源队列读取并写入一个或多个队列,这确实复制了 MQMD 和消息体。

设置如下所示:

创建三个QLOCAL对象,第一个对象将被使用一个应用程序,该应用程序将复制到第二个对象以供记录消息的应用程序使用,第三个对象将由您的“业务案例”应用程序使用:

DEFINE QLOCAL(INBOUND.QUEUE)
DEFINE QLOCAL(INBOUND.QUEUE.LOGGER)
DEFINE QLOCAL(INBOUND.QUEUE.PROCESSOR)

选项 5

有一种名为MQ 消息复制 (MQMR)的商业产品可以使用 MQ API 出口将发送到“业务案例”应用程序队列的消息精确复制到一个或多个其他队列。我个人没有使用过这个,但设置只是两个 QLOCAL 队列,第一个将由您的“业务案例”应用程序使用,第二个将由记录消息的应用程序使用。

DEFINE QLOCAL(INBOUND.QUEUE)
DEFINE QLOCAL(INBOUND.QUEUE.LOGGER)
于 2017-11-05T07:30:26.560 回答
1

我只是稍微调整了您的代码,就可以浏览消息了。

namespace XmsBrowser
{
    class BrowseMessages
    {
        IConnection connectionWMQ;
        IQueueBrowser queueBrowser;

    static void Main(string[] args)
    {
        BrowseMessages pgm = new BrowseMessages();
        pgm.browseMessage();
    }

    private void browseMessage()
    {
        try
        {
            XMSFactoryFactory xMSFactoryFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);

            // Create WMQ Connection Factory.
            IConnectionFactory connectionFactory = xMSFactoryFactory.CreateConnectionFactory();

            connectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, "localhost");
            connectionFactory.SetIntProperty(XMSC.WMQ_PORT, 1414);
            connectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, "QM_SVRCONN_CHANNEL");
            connectionFactory.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT);
            connectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "QMDEMO");

            // Create connection.
            connectionWMQ = connectionFactory.CreateConnection();
            //connectionWMQ.ExceptionListener = new ExceptionListener(OnXMSException);

            // Create session
            ISession sessionWMQ = connectionWMQ.CreateSession(false, AcknowledgeMode.AutoAcknowledge);

            IDestination destination = sessionWMQ.CreateQueue("Q1");

            queueBrowser = sessionWMQ.CreateBrowser(destination);

            Thread thread = new Thread(KeepBrowsingMessaegs);
            thread.Start();
            connectionWMQ.Start();
            thread.Join();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        Console.ReadKey();
    }

    private void KeepBrowsingMessaegs()
    {
        IEnumerator queueEnumerator = queueBrowser.GetEnumerator();
        while (true)
        {
            if (queueEnumerator.MoveNext())
            {
                ITextMessage textMessage = queueEnumerator.Current as ITextMessage;
                if (textMessage != null)
                {
                    System.Diagnostics.Trace.Write(textMessage);
                }
            }else
            {
                break;
            }
        }
       }
    }
}
于 2017-11-06T13:51:05.830 回答