【问题标题】:why jms Client acknowledge is not working为什么 jms 客户端确认不起作用
【发布时间】:2021-01-08 00:36:02
【问题描述】:

我正在尝试从 ActiveMQ 队列中检索消息。我将会话设置为Session.CLIENT_ACKNOWLEDGE。当我从服务器收到消息时,它会自动确认,尽管我没有在消息上调用确认。下面是我正在做的示例代码:

connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Destination destination = session.createQueue(queue);
consumer = session.createConsumer(destination);
connection.start();
Message message = consumer.receive(1);

上面的代码 sn-p 有效,我确实从队列中获取了消息。问题是消息从队列中消失了,尽管我没有确认消息。任何指示为什么会发生这种情况。我几乎整个下午都在调试这个问题,但没有运气。这是一个 Spring 启动应用程序。

我让 client_ack 在 jmsTemplate 中工作。下面是代码。

public Object retrieve() {
        return this.jmsTemplate.execute(session -> {
            session.recover();
            MessageConsumer consumer = session.createConsumer(
                    this.jmsTemplate.getDestinationResolver().resolveDestinationName(session, queue, false));
            try {
                Message received = consumer.receive(1);
                if (received != null) {
                    return this.messageConverter.fromMessage(received);
                }
            }
            catch (Exception e) {
                return null;
            }
            finally {
                consumer.close();
            }
            return null;
        }, true);
    }

我现在看到的问题是我的应用在重新启动后看不到这些消息。我尝试运行 session.recover() 但它没有任何区别。感谢您的帮助。

使用 jmsTemplate 的工作代码如下:

public Object retrieve() {
        return this.jmsTemplate.execute(session -> {
            MessageConsumer consumer = session.createConsumer(
                    this.jmsTemplate.getDestinationResolver().resolveDestinationName(session, queue, false));
            try {
                Message received = consumer.receive(1);
                session.recover();
                if (received != null) {
                    return this.messageConverter.fromMessage(received);
                }
            }
            catch (Exception e) {
                return null;
            }
            finally {
                consumer.close();
            }
            return null;
        }, true);
    }

【问题讨论】:

  • 我使用的是 5.14.4 版本。我正在从 ActiveMQ 管理控制台观看队列。运行代码后,我在队列中看不到任何消息。我在 IBM MQ 服务器中也看到了相同的行为。
  • 谢谢贾斯汀。我可以让 jmsTemplate 与 client_ack 一起工作,但就像你说的那样,尽管这些消息现在存在,但似乎在队列中看不到这些消息。这是与 client_ack 一起使用的代码,但正如我所说,当应用程序再次运行时,虽然它们在队列中,但它看不到消息。我将在帖子中添加此代码。再次感谢您对此进行调查。
  • 我现在不太明白问题出在哪里。看起来你原来的问题已经消失了,但你仍然在你的问题中引用它。看来你现在的问题完全不同了。请澄清您的问题,否则它可能会被关闭。
  • 嗨,贾斯汀,感谢您对此进行调查。我解决了。我将在帖子中发布我的发现。解决方法是将会话设置为非事务处理,拉取消息后执行 session.recover(),最后将最大重新发送次数设置为 -1(无限制)。 -

标签: spring-boot jms


【解决方案1】:

对于可能遇到此问题的任何人,我已执行以下操作来解决此问题:

  1. 将会话设置为非事务。如果您使用 jmsTemplate,这是默认且唯一的选项。如果您正在创建自己的消费者,则需要在创建 jms 连接时将会话创建为非事务性
  2. 如果您要创建自己的消费者,则需要将会话设置为 CLIENT_ACKNOWLEDGE。
  3. 检查重新传递的最大数量到所需的值。这将因产品而异:ActiveMQ、IBM MQ 等。
  4. 检索消息后调用 session.recover()。

我更新了原帖中使用 jmsTemplate 的工作代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-30
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 2020-03-30
    相关资源
    最近更新 更多