【问题标题】:JMS - producer is closedJMS - 生产者已关闭
【发布时间】:2019-09-26 02:25:52
【问题描述】:

以下代码尝试使用 JMS 在队列上发送消息。

connection = jmsConnectionFactory.createConnection();
connection.start();

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queueName);

MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);

它大部分时间都可以工作,但是在运行并行发送许多消息的压力测试时,我发现了一次以下异常:

Caused by: javax.jms.IllegalStateException: The producer is closed
        at org.apache.activemq.ActiveMQMessageProducer.checkClosed(ActiveMQMessageProducer.java:195)
        at org.apache.activemq.ActiveMQMessageProducerSupport.setDeliveryMode(ActiveMQMessageProducerSupport.java:136)

setDeliveryMode() 中抛出异常。 我看过其他关于同一问题的帖子,但就我而言,我没有使用共享会话,也没有使用共享连接。

我正在运行 ActiveMQ 5.14.5。

【问题讨论】:

  • 您能分享更多您的客户端代码吗?您是否正在为您发送的每条消息创建连接、会话和生产者?如果是这样,那是你绝对应该避免的反模式。
  • 我看到很多其他帖子抱怨共享会话引起的问题。我正在考虑使用连接池,但我宁愿不重用会话,除非存在不会产生问题的已知模式。
  • 没有那么多代码了。设置redelivery模式后,发送一些消息并返回。
  • 您当然不想在多个线程之间同时使用会话,但是 JMS 连接是线程安全的,因此您可能只需要其中的 1 个,然后您可以每个线程有一个会话,而不是而不是每次发送消息时创建一个。生产者也是如此 - 每个线程一个。
  • 我不太关心你的代码在调用 setDeliveryMode() 后会做什么,因为我关心的是如何定义所有变量以及并发线程如何实际使用包含类发送消息。

标签: jms activemq


【解决方案1】:

查看org.apache.activemq.ActiveMQMessageProducer 的代码,closed 变量(由堆栈跟踪顶部的checkClosed() 方法检查)初始化为false,因此必须将其设置为true 抛出此异常。据我所知,仅当生产者本身、发起会话或发起连接关闭时,它才设置为true。由于其他一些故障,连接和/或会话可能正在后台关闭,而生产者的这种异常是该问题的第一个明显症状。

在任何情况下,如果没有关于您的代码的至少一些额外细节或理想情况下是 minimal, reproducible example,实际上不可能得出可靠的结论。

【讨论】:

  • 鉴于用户声明正在进行压力测试,一种可能性是他们已经超过了代理内存限制等,并且由于本机线程创建失败等原因导致连接断开。
猜你喜欢
  • 2021-12-31
  • 2021-06-19
  • 2011-12-07
  • 2012-05-18
  • 2016-04-23
  • 2015-02-03
  • 2017-07-13
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多