【问题标题】:How to discard messages from queue using Java/JMS?如何使用 Java/JMS 从队列中丢弃消息?
【发布时间】:2014-11-18 07:08:28
【问题描述】:

我们有一个使用 JMS 从 IBM Websphere 队列(7.5 版)同步读取 4MB 消息的应用程序。在某些情况下,我想丢弃队列中的消息而不读取它们。我试图弄清楚是否有一种方法可以在不读取整个 4MB 消息的情况下以编程方式执行此操作,这需要几秒钟(可能有数百条消息需要丢弃)。在没有 discard() 方法(或类似方法)的情况下,这是我尝试过的:

BytesMessage msg = (BytesMessage)queueReceiver.receiveNoWait();
bytesRead = msg.readBytes(msgBytes, 1024); // just read 1024 bytes
queueReceiver.close();

上面的代码并不比从队列中检索整个 4MB 消息更快(通过读入更大的缓冲区)。这让我相信在调用 readBytes() 之前,receiveNoWait() 调用正在将整个消息下载到内部缓冲区中。我可以提供的唯一其他信息是在会话开始时队列设置为“自动确认”:

queueSession = queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);

如果我将其更改为 CLIENT_ACKNOWLEDGE 并使用 msg.acknowledge() 确认消息,会产生预期的效果吗?还是我缺少什么?

感谢您的帮助, 道格

【问题讨论】:

  • 在activemq中你可以只使用消息,但我不确定这是否意味着阅读消息来做到这一点。确实是个好问题。
  • 您在如何将消息从服​​务器拉到客户端方面是非常正确的。是否有关于消息的某些内容,例如确定是否应删除消息的属性?还是其他一些标准?
  • 数据库中的状态码告诉应用程序它不再需要队列中的消息(由于其他一些故障条件)。我无法清除整个队列,因为还有其他线程在处理其他消息。我只是想清除特定消息而不下载它们,而这似乎使用 JMS 是不可能的。

标签: java queue jms mq


【解决方案1】:

没有其他方法,必须消耗一条消息才能将其从队列中删除。

从 AUTO_ACKNOWLEDGE 更改为 CLIENT_ACKNOWLEDGE 不会有任何区别,因为确认是告诉消息传递提供程序从队列中删除消息的方式。 AUTO_ACKNOWLEDGE 选项告诉 JMS 客户端自动向提供者发送确认以删除消息,而应用程序使用 CLIENT_ACKNOWLEDGE 明确告诉提供者删除消息。

您可能会考虑为您不打算使用的消息设置过期时间。设置了过期时间的消息,在过期时间结束后将无法发送。通读消息的 JMSExpiration 属性。

【讨论】:

    【解决方案2】:

    考虑到这一点,这里可能还有另一种方式; MQ 具有 PCF 消息的概念 - 简单地说,就是能够将管理命令作为消息发送到队列管理器。

    JMS 可以发送这些消息 - 因此当您知道不再需要任何消息时,可以发送一个 CLEAR_QUEUE 命令。

    这是一种相当广泛的方法 - 清除整个队列,但这取决于您删除消息的标准。

    我可以看到选择性删除消息的用例 - 也许值得在 IBM developerWorks 站点上提出“增强请求”RFE?

    【讨论】:

    • 如果 IPPROCS 和/或 OPPROCS 不为零,PCF CLEAR_QUEUE 命令将不起作用。
    【解决方案3】:

    据我所知,JMS 无法读取消息的一部分。您只能使用 C 或 Java(非 JMS)来做到这一点。

    MQGetMessageOptions gmo = new MQGetMessageOptions();
    gmo.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING;
    
    MQMessage getMsg = new MQMessage();
    try
    {
       /* get the message with only 1 byte of message data */
       _inQ.get(getMsg, gmo, 1);
    }
    catch (MQException e)
    {
       System.err.println(e.getLocalizedMessage() );
    }
    

    【讨论】:

    • 大家,感谢您的回复。我确实尝试过使用客户端确认模式,正如 Shashi 预测的那样,它没有任何效果。不幸的是,我不能只清除整个队列。在这一点上,我的选择是让消息过期或完整下载它们。不幸的是,让它们过期对我来说似乎不是一个好的选择。测试表明,当我们孤立许多 4MB 消息而其他线程正在检索消息(我们使用相关 ID 检索它们)时,队列管理器的性能会下降。再次感谢大家的反馈。
    猜你喜欢
    • 2015-03-17
    • 2014-09-16
    • 2012-03-20
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 2018-03-22
    • 2023-03-08
    • 2018-01-28
    相关资源
    最近更新 更多