我已经构建了一个小型Java程序,该程序使用MQ客户端类与Websphere MQ服务器及其队列进行对话。我想要的是定期查询某个队列的大小,错误深度。每10秒。

我所做的,示意性地:

  • qm = new MQQManager()
  • q = qm.accessQueue()
  • depth = q.getCurrentDepth()
  • (用depth做些事)
  • q.close()
  • qm.close()

  • 这就像一个魅力!

    出于懒惰,我编写了代码,每次都要经过上述序列的所有6个步骤。因此,我最终每10秒重复一次此循环。在大约半小时内,监视服务器的人员告诉我,我已打开153个实例。显然,仅在队列和QM上执行close()不足以自己清理。

    我将进行明显的修复,并保持QM并排队等待程序的生命周期。但是有人可以告诉我为什么我以前的方法会泄漏资源吗?如果我选择遵循这种方法,我该怎么办?

    更新(2017-01-25)

    计时接受

    关于性能和未提交的消息,Roger提供了一些漂亮的代码和一些有用的解释。太酷了,但是Eugene的回答恰好(并且最少)足以解决我的问题,而且他的回答要快一些。在根据Eugene的建议将close()更改为disconnect()之后,我的小应用程序现在可以完全满足我的要求。现在我对谁应该获得复选标记感到不安。我对你们俩表示歉意!

    我已经完全满足了我的要求,并且我想我已经解决了这个问题,但是我还要补充一点,我感谢Roger为该问题提供的有用信息,为以后的任何其他读者提供了周到的解答。希望其他人会听他的话,而不是跟随我。

    性能

    老实说,我不对表现一无所知。该服务器比当前执行的操作所需的胖得多,并且我的监视客户端(此问题的主题)在通常为空的开发计算机上运行。我希望它在一两天内能达到目的,然后我将其丢弃。同时,如果每10秒连接一次会导致性能问题,则它们应该平衡Raspberry Pi或其他设备的负载。

    未提交的邮件

    我认为这也不是问题。发送应用程序在几毫秒内以大约1-5条消息的小批量入队,并立即提交。接收应用程序(我写的一个客户端,很可能有问题)不断地在队列上侦听,分别接收和确认(提交)每条消息。因此,我有把握地确定不会超过1条,可能是5条未确认的消息。与...的参数相比,该数字微不足道。

    我的实际问题

    每天早上几乎同一时间,其中涉及几到几百条消息的处理延迟在5到20分钟之间。我怀疑我的接收客户端因MQS以外的“挂起”网络IO操作而停滞了。我要探索的第一步是证明MQS上确实存在队列中的等待消息,并且没有被接收。我想看看该队列何时开始建立,它坐在那里多长时间以及一旦我的客户再次醒来它消退的速度如何。

    这种连接每天可看到2,000至10,000条消息,其峰值对应于下午和晚上的批处理过程,但是延迟仅在早晨发生,通常实际发送的消息量很小。我想查看队列大小的日志,以更好地了解正在发生的事情。下一步,我可能需要在接收客户端中进行更多检测。

    环境

    就其价值而言,服务器正在运行WSMQ 6,因此我的客户端使用阻塞等待队列获取,而不是我本来希望使用的灵活的异步通知过程。我的接收客户端是在VM中的RHEL下运行的独立C应用程序。

    最佳答案

    哇!不是很有效的代码。通过FAR进行连接是最昂贵的MQ API调用。同样,获得队列深度是没有意义的。它为您提供队列中所有未提交和已提交的消息。即队列深度可能表示队列中有5条消息,但是您的程序只能检索3条消息!您可能会说MQ坏了,但实际上,没有提交2条消息,因此,消费者无法使用。

    如果您真的想每10秒获取和记录一次信息,请保持联系。

    这是一种更好的方法:

    boolean working = true;
    int openOptions  = CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING;
    int depth = 0;
    MQQueueManager qm = null;
    MQQueue q = null;
    
    try
    {
       qm = new MQQueueManager("MQA1");
    
       while (working)
       {
          try
          {
             q = qm.accessQueue("TEST.Q1", openOptions);
             depth = q.getCurrentDepth();
    //         (do something with depth)
          }
          catch (MQException e)
          {
             System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
             System.out.println(e.getLocalizedMessage() );
             working = false;
          }
          finally
          {
             if (q != null)
             {
                q.close();
                q = null;
             }
          }
    
          try
          {
             if (working)
                Thread.sleep(10*1000); // time in milliseconds
          }
          catch (InterruptedException ie) {}
       }
    }
    catch (MQException e)
    {
       System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
       System.out.println(e.getLocalizedMessage() );
    }
    finally
    {
       try
       {
          if (q != null)
             q.close();
       }
       catch (MQException e)
       {
          System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
          System.out.println(e.getLocalizedMessage() );
       }
    
       try
       {
          if (qm != null)
             qm.disconnect();
       }
       catch (MQException e)
       {
          System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
          System.out.println(e.getLocalizedMessage() );
       }
    }
    

    关于java - 如何避免太多的IBM MQ channel 实例?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41815989/

    10-12 03:36