当消息可用时,JMS的receiveNoWait()方法是否保证消息传递?

3

你好,我正在编写一些简单的测试场景,其中我执行以下源代码:

这是我的send()方法:

public void send() throws JMSException {

    Session session = null;
    MessageProducer producer = null;

    try {
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        Destination destination = session.createQueue("TEST.FOO");

        producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        byte[] uselessData = new byte[1024];

        BytesMessage message = session.createBytesMessage();
        message.writeBytes(uselessData);

        producer.send(message);

    } finally {
        producer.close();
        session.close();
    }
}

这是我的receive()方法:

public void receive() throws JMSException {

    Session session = null;
    MessageConsumer consumer = null;

    try {
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue("TEST.FOO");
        consumer = session.createConsumer(destination);

        Message hugeMessage = consumer.receiveNoWait();

        if (hugeMessage == null) {
            System.out.println("Message was not received");
            unsucsesfullCount++;
        } else {
            if (hugeMessage instanceof BytesMessage) {
                System.out.println("Message received");
            }
        }
    } finally {
        consumer.close();
        session.close();
    }

}

我执行:

send();
receive();
receiveNoWait() 方法返回的消息值始终为null
我的问题是,当代理中存在消息时,receiveNoWait() 是否保证消息传递?send() 成功执行,因此目标至少有一条消息。
我在规范中搜索过,但并没有明确说明在客户端必须通过 receiveNoWait() 明确接收代理端可用的消息。
另外,我想问的是,如果 receiveNoWait() 没有可用的消息,它是否应该触发代理中的某些刷新消费者进程,以便下一个 receiveNoWait() 将接收到消息?
我提供的示例代码在 ActiveMQ 上运行,但我的问题更多地涉及概念而非特定提供程序,因为我对其他 JMS 提供程序也有同样的观察。

在SO提问的好例子! - BillMan
1个回答

4
不,规范并不保证任何对 receiveNoWait 的调用都会返回一条消息,有可能会返回,也有可能不会。当使用 receiveNoWait 时,您必须始终检查是否返回了空值,并相应地采取措施。
在 ActiveMQ 中,如果代理已将消息分派给消费者预取缓冲区并且该消息立即可用,则客户端将返回一条消息;否则,它将返回空值。
其他实现可能确实会向代理发送轮询请求。例如,Qpid JMS 使用 AMQP 链路排空请求来要求代理发送任何可供分派的消息,代理将发送这些消息或发出链路排空信号,并表示没有准备好的消息。
简而言之,如何实现 receiveNoWait 完全取决于客户端和代理,但无论如何,您总是需要考虑到您可能无法从该方法中获取到消息的情况。

谢谢你的回答,Tim。我的理解是一样的,但由于规范缺乏适当的解释,我决定寻找更多的意见。 - Altair
请注意,针对此问题澄清Message.receiveNoWait()的预期行为存在一个旧的未解决的标准错误报告。 - user7610
我认为可以通过将预取限制设置为0来禁用activemq中的此行为(即使receiveNoWait实际上检查代理)。https://activemq.apache.org/what-is-the-prefetch-limit-for - robd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接