【问题标题】:queueBrowser.GetEnumerator() doesnt get any messages | IBM MQ XMS C# clientqueueBrowser.GetEnumerator() 没有收到任何消息 | IBM MQ XMS C# 客户端
【发布时间】:2018-04-09 07:29:56
【问题描述】:

我们正在使用 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);
                }
            }
        }
    }

【问题讨论】:

  • 我已安装完整的 MQ v9 客户端
  • 队列浏览器和队列消费者设置在同一个队列上。因此,队列消费者甚至在队列浏览器有机会之前就删除了消息。一旦我停止了队列消费者,队列浏览器就能够接收消息。但是现在我的问题是如何确保队列浏览器和队列消费者协同工作?
  • Thaks JoshMC。作为业务案例的一部分,我们让消费者运行以读取消息,并希望设置浏览器以便我们只获取消息的副本,以便我们可以在单独的应用程序中跟踪它以记录收到的所有消息。
  • 我编辑了问题,包括说除了消息浏览器之外还有并发消息消费者

标签: c# ibm-mq xms


【解决方案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;
            }
        }
       }
    }
}

【讨论】:

  • 并发消费者工作时,此浏览器是否获取消息。我认为在队列上设置消息消费者时浏览器不会收到消息
  • 这很明显。消费者从队列中删除消息。浏览器无法获取已删除的消息。
【解决方案2】:

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

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


选项 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.LOGGERINBOUND.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 Message Replication (MQMR) 的商业产品可以使用 MQ API 出口将发送到“业务案例”应用程序队列的消息精确复制到一个或多个其他队列。我个人没有使用过,但设置只是两个 QLOCAL 队列,第一个将由您的“业务案例”应用程序使用,第二个将由记录消息的应用程序使用。

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

【讨论】:

  • 我喜欢我的商业案例的“选项 1”
  • 感谢您的接受。你也会奖励赏金吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 2019-01-28
  • 2022-10-30
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
相关资源
最近更新 更多