ActiveMQ消费者连接Broker时是否每次创建地址?特殊格式地址疑问
我们实现ActiveMQSecurityManager5接口自定义安全管理器时发现:当已有<address-name>地址存在,新订阅者/消费者连接Broker时,会触发CheckType.CREATE_ADDRESS授权事件,对应的地址格式为<address-name>::<client-id>.<address-name>;在此事件之前,同样的地址还会触发CheckType.CREATE_NON_DURABLE_QUEUE事件。
我对为何会创建这种FQQN队列格式的新地址感到困惑,这是否属于ActiveMQ路由逻辑的细节?
编辑补充
添加了订阅时CREATE_ADDRESS事件的栈追踪信息。ActiveMQSecurityManager5类中的authorize方法如下:
@Override public boolean authorize(Subject subject, Set<Role> roles, CheckType checkType, String address) { System.out.println("Checktype: " + checkType); System.out.println("Address: "+ address); if (checkType.equals(CheckType.CREATE_ADDRESS) && address.contains("::")) { new Exception("trace").printStackTrace(); } return true; }
以下是该异常的栈追踪信息,其中newaddress是消费者尝试连接的地址,bad是消费者的client ID:
Checktype: CREATE_ADDRESS Address: newaddress::bad.newaddress java.lang.Exception: trace at org.test.JwtPlugin.authorize(JwtPlugin.java:73) at org.apache.activemq.artemis.core.security.impl.SecurityStoreImpl.check(SecurityStoreImpl.java:344) at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.securityCheck(ServerSessionImpl.java:527) at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.createQueue(ServerSessionImpl.java:770) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTSubscriptionManager.findOrCreateQueue(MQTTSubscriptionManager.java:187) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTSubscriptionManager.createQueueForSubscription(MQTTSubscriptionManager.java:174) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTSubscriptionManager.addSubscription(MQTTSubscriptionManager.java:108) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTSubscriptionManager.addSubscriptions(MQTTSubscriptionManager.java:310) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTProtocolHandler.handleSubscribe(MQTTProtocolHandler.java:382) at org.apache.activemq.artemis.core.protocol.mqtt.MQTTProtocolHandler.act(MQTTProtocolHandler.java:179) at org.apache.activemq.artemis.utils.actors.Actor.doTask(Actor.java:32) at org.apache.activemq.artemis.utils.actors.ProcessorBase.executePendingTasks(ProcessorBase.java:69) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run(ActiveMQThreadFactory.java:120)
问题解答
这种格式的地址属于ActiveMQ Artemis处理MQTT订阅时的内部路由逻辑细节,具体原因如下:
- MQTT订阅的队列生成规则
从栈追踪能看到,整个流程由MQTTSubscriptionManager触发。MQTT协议本身没有"地址-队列"的分离概念,Artemis为了适配MQTT,会给每个MQTT订阅生成专属队列:
- 队列名称格式为
<client-id>.<address-name>,确保每个客户端的订阅队列唯一 - 这里的
<address-name>::<client-id>.<address-name>是**Fully Qualified Queue Name (FQQN)**格式,用::分隔地址和队列名,是Artemis内部用来唯一标识队列的规范格式
为何触发CREATE_ADDRESS事件
当创建这个专属队列时,Artemis的安全检查逻辑会把FQQN当作"地址"参数传入授权方法。这是因为在Artemis的安全模型中,队列的创建会关联到其对应的地址权限检查,而内部处理时会把FQQN格式的队列标识符传递给授权接口,从而触发了CREATE_ADDRESS事件。事件顺序的逻辑
- 先触发
CREATE_NON_DURABLE_QUEUE:对应创建<client-id>.<address-name>这个非持久化队列的操作 - 再触发
CREATE_ADDRESS:是安全检查流程中对队列关联的FQQN格式标识符的额外权限校验,属于内部逻辑的一部分
这不是Bug,而是Artemis适配MQTT协议时,为了管理客户端专属订阅队列而产生的内部权限检查行为,属于路由和安全模型结合的细节。
内容的提问来源于stack exchange,提问作者TdBm

