Linux下C++ CMS客户端连接ActiveMQ Artemis权限问题
问题背景
Linux环境下通过C++应用使用CMS Client库连接客户的ActiveMQ Artemis消息代理,无管理员权限。connectionFactory->createConnection()执行正常(用户名密码验证通过),但调用connection->start()时失败,报错如下:
AMQ229213: User: ******** does not have permission='CREATE_NON_DURABLE_QUEUE' for queue d002d98a-4343-4f0a-ad0d-cf9a6941b36d on address ActiveMQ.Advisory.TempQueue FILE: org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection.convertException(OpenWireConnection.java), LINE: 461 FILE: org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection.act(OpenWireConnection.java), LINE: 373 FILE: org.apache.activemq.artemis.utils.actors.ThresholdActor.doTask(ThresholdActor.java), LINE: 73 FILE: org.apache.activemq.artemis.utils.actors.ProcessorBase.executePendingTasks(ProcessorBase.java), LINE: 68 FILE: org.apache.activemq.artemis.utils.actors.OrderedExecutor.doTask(OrderedExecutor.java), LINE: 57 FILE: org.apache.activemq.artemis.utils.actors.OrderedExecutor.doTask(OrderedExecutor.java), LINE: 32 FILE: org.apache.activemq.artemis.utils.actors.ProcessorBase.executePendingTasks(ProcessorBase.java), LINE: 68 FILE: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java), LINE: 1136 FILE: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java), LINE: 635 FILE: org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run(ActiveMQThreadFactory.java), LINE: 118 FILE: activemq/core/ActiveMQConnectionFactory.cpp, LINE: 360
代理管理员要求修改客户端避免创建队列,但业务代码中并未主动创建队列,仍触发该问题。
问题原因
CMS Client基于OpenWire协议实现,默认会在连接启动时自动订阅Advisory消息(用于接收代理状态、消费者上下线通知等事件),而订阅这类消息需要创建一个临时队列(对应报错中的ActiveMQ.Advisory.TempQueue地址)。ActiveMQ Artemis对临时队列的创建会校验CREATE_NON_DURABLE_QUEUE权限,当前用户没有该权限,因此connection->start()执行失败。
解决方案
1. 禁用Advisory消息订阅
通过配置CMS的ConnectionFactory属性,关闭自动订阅Advisory消息,从而避免创建临时队列。示例代码如下:
// 初始化连接工厂 ActiveMQConnectionFactory* connectionFactory = new ActiveMQConnectionFactory("tcp://your-broker-address:61616"); // 禁用主题和队列的Advisory监听 connectionFactory->setWatchTopicAdvisories(false); connectionFactory->setWatchQueueAdvisories(false); // 部分CMS版本可直接设置全局禁用Advisory的属性 connectionFactory->setStringProperty("disableAdvisory", "true"); // 后续创建连接并启动 Connection* connection = connectionFactory->createConnection("username", "password"); connection->start();
注意:不同版本的CMS Client属性名可能略有差异,需根据使用的版本调整配置项。
2. 切换为Artemis原生Core JMS客户端
如果CMS Client的配置无法生效,建议改用ActiveMQ Artemis官方提供的C++ Core JMS客户端。原生客户端默认不会自动创建Advisory相关的临时队列,与Artemis代理的兼容性更好,能更精细地控制连接行为,避免不必要的权限校验。
3. 排查业务代码中的临时队列创建
检查业务代码中是否存在主动调用createTemporaryQueue()或createTemporaryTopic()的逻辑,若有则移除相关代码,避免触发临时队列创建。
注意事项
- 禁用Advisory消息后,将无法接收代理的状态通知(如队列创建/删除、消费者上线/下线等),若业务依赖这类通知,需与代理管理员沟通权限调整或修改业务逻辑。
- 若使用CMS Client,建议确认版本与ActiveMQ Artemis的兼容性,部分旧版本可能存在配置属性不生效的问题。
内容的提问来源于stack exchange,提问作者peti

