You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式ActiveMQ Artemis通过JMX创建Address/Divert时阻塞问题

嵌入式ActiveMQ Artemis JMX创建Address死锁问题解决

问题根源分析

死锁的核心逻辑是循环锁等待:

  • beforeCreateQueue钩子运行在持有PostOfficeImpl对象锁的Broker主线程中
  • 此时发起JMX的createAddress/createDivert操作,RMI线程会尝试再次获取PostOfficeImpl锁(地址创建需要修改路由表,必须持有该锁)
  • 最终形成:Broker主线程持锁等JMX返回,RMI线程等锁被Broker主线程释放的死锁

直接解决方案(绕过死锁)

方案1:异步执行地址创建

避免在同步钩子中发起修改类JMX调用,改用异步线程执行:

@Override
public boolean beforeCreateQueue(QueueConfiguration queueConfig, boolean autoCreateAddress, Map<String, Object> options) throws Exception {
    if (!broker.getPostOffice().addressExists(queueConfig.getAddress())) {
        // 用Broker内置线程池或自定义线程池异步执行
        broker.getExecutorFactory().getExecutor().submit(() -> {
            try {
                ManagementService managementService = broker.getManagementService();
                managementService.createAddress(queueConfig.getAddress(), RoutingType.MULTICAST, false);
            } catch (Exception e) {
                // 自行处理异常日志
            }
        });
    }
    return true;
}

方案2:直接调用Broker本地API替代JMX

跳过JMX的跨线程调用,直接用Broker内部API创建地址,避免锁竞争:

@Override
public boolean beforeCreateQueue(QueueConfiguration queueConfig, boolean autoCreateAddress, Map<String, Object> options) throws Exception {
    if (!broker.getPostOffice().addressExists(queueConfig.getAddress())) {
        AddressInfo addressInfo = new AddressInfo(queueConfig.getAddress(), RoutingType.MULTICAST);
        // 直接调用PostOffice本地方法创建地址
        broker.getPostOffice().addAddress(addressInfo, false);
    }
    return true;
}

嵌入式权限配置修正

嵌入式环境下,代码配置优先级高于XML,需直接通过代码设置权限:

Configuration config = new ConfigurationImpl();
// 禁用安全(如果不需要权限控制)
config.setSecurityEnabled(false);
// 若需启用安全,直接在代码中配置角色权限
Map<String, Set<String>> securityRoles = new HashMap<>();
securityRoles.put("createAddress", Collections.singleton("admin"));
config.putSecurityRoles(securityRoles);
// 初始化启动Broker
ActiveMQServer server = ActiveMQServers.newActiveMQServer(config);
server.start();

验证步骤

  1. 启动嵌入式Broker后,用MQTT客户端连接现有地址
  2. 触发队列创建逻辑(如客户端订阅新队列)
  3. 通过VisualVM检查线程状态,确认无BLOCKED状态的RMI线程
  4. 验证目标地址是否成功创建

内容的提问来源于stack exchange,提问作者TdBm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:24:59