无ActiveMQ Artemis发送权限时非持久化消息无报错问题咨询
问题:无SEND权限时,非持久化消息发送无报错?
我尝试向无SEND权限的队列发送两类消息:
- 设置
producer.setDeliveryMode(DeliveryMode.PERSISTENT)时,控制台正常显示无权限报错; - 设置
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT)时,无任何报错提示且消息未发送至队列。
希望两种场景均能触发报错,请问这是ActiveMQ Artemis Broker的特性吗?
相关配置与代码
broker.xml 配置
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd"> <core xmlns="urn:activemq:core"> <name>localhost</name> <bindings-directory>./data/messaging/bindings</bindings-directory> <journal-directory>./data/messaging/journal</journal-directory> <large-messages-directory>./data/messaging/largemessages</large-messages-directory> <paging-directory>./data/messaging/paging</paging-directory> <!-- true to expose ActiveMQ Artemis resources through JMX --> <jmx-management-enabled>true</jmx-management-enabled> <!-- Acceptors --> <acceptors> <acceptor name="netty">tcp://localhost:61616</acceptor> </acceptors> <!-- Other config --> <security-settings> <!--security for example queue--> <security-setting match="exampleQueue"> <permission roles="amq" type="createDurableQueue"/> <permission roles="amq" type="deleteDurableQueue"/> <permission roles="amq" type="createNonDurableQueue"/> <permission roles="amq" type="deleteNonDurableQueue"/> <permission roles="amq" type="consume"/> <permission roles="no" type="send"/> <permission roles="amq" type="browse"/> </security-setting> <security-setting match="TestQueue"> <permission roles="amq" type="createDurableQueue"/> <permission roles="amq" type="deleteDurableQueue"/> <permission roles="amq" type="createNonDurableQueue"/> <permission roles="amq" type="deleteNonDurableQueue"/> <permission roles="amq" type="consume"/> <permission roles="no" type="send"/> <permission roles="amq" type="browse"/> </security-setting> <security-setting match="TestQueueSecond"> <permission roles="amq" type="createDurableQueue"/> <permission roles="amq" type="deleteDurableQueue"/> <permission roles="amq" type="createNonDurableQueue"/> <permission roles="amq" type="deleteNonDurableQueue"/> <permission roles="no" type="consume"/> <permission roles="no" type="send"/> </security-setting> </security-settings> <addresses> <address name="exampleQueue"> <anycast> <queue name="exampleQueue"/> </anycast> </address> <address name="TestQueue"> <anycast> <queue name="TestQueue"/> </anycast> </address> <address name="TestQueueSecond"> <anycast> <queue name="TestQueueSecond"/> </anycast> </address> </addresses> </core> </configuration>
Java 生产者代码
@RestController public class Producer implements Serializable { String url = "tcp://localhost:61616"; @GetMapping("/send") public String sendMessage() throws JMSException { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url); connectionFactory.setUser("test"); connectionFactory.setPassword("qwe123"); Connection connection = connectionFactory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination destination = session.createQueue("exampleQueue"); MessageProducer producer = session.createProducer(destination); producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message message = session.createTextMessage("BodyTextMessage"); message.setStringProperty("TEST", "TEST"); producer.send(message); String body = message.getBody(String.class); connection.close(); return body; } }
解答
这确实是ActiveMQ Artemis的默认行为,核心原因在于非持久化消息的发送确认机制差异:
- 持久化消息默认要求broker返回发送确认(ACK),权限校验失败时,broker会主动返回错误信息,客户端能捕获到该错误;
- 非持久化消息在默认的
Session.AUTO_ACKNOWLEDGE模式下,客户端不会等待broker的确认,消息发送后直接判定为成功,即便broker因权限问题丢弃了消息,客户端也无法感知。
要让非持久化消息也触发权限报错,可通过以下两种方式解决:
方式1:调整Session的确认模式
创建Session时使用Session.CLIENT_ACKNOWLEDGE模式,并在发送消息后手动确认,强制broker返回处理结果:
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); // ...发送消息逻辑 message.acknowledge();
这种模式下,broker会在完成权限校验等处理后返回确认,权限失败时客户端会收到对应的报错。
方式2:修改broker配置,强制非持久化消息返回确认
在broker.xml的<core>节点下添加配置,让broker对所有非持久化消息都发送确认:
<core> <!-- 保留原有配置 --> <force-acknowledge-on-non-durable-send>true</force-acknowledge-on-non-durable-send> </core>
开启该配置后,无论客户端使用哪种确认模式,broker都会返回非持久化消息的处理结果,权限校验失败时客户端即可捕获到错误。
内容的提问来源于stack exchange,提问作者user23253016
相关产品推荐
相关产品推荐

