嵌入式ActiveMQ Artemis远程JMX连接失败问题求助
解决嵌入式ActiveMQ Artemis 2.38.0 + JMX远程连接问题(Spring Boot 3.x/Java 17)
核心问题分析
你遇到的连接拒绝错误,本质是嵌入式Artemis默认未启用远程JMX访问,再加上Java 17对RMI连接的严格限制、Spring Boot 3.x的JMX自动配置可能冲突,导致JMX服务无法被远程访问。
分步解决方案
1. 完善嵌入式Artemis的JMX配置
修改嵌入式服务器初始化代码,显式开启远程JMX并配置RMI端口:
Configuration mqConfig = new ConfigurationImpl(); server = new EmbeddedActiveMQ(); // 原有配置 mqConfig.addAcceptorConfiguration("tcp", "tcp://127.0.0.1:61616"); mqConfig.setSecurityEnabled(false); mqConfig.setMessageCounterEnabled(true); mqConfig.setMessageCounterSamplePeriod(500); mqConfig.setMessageCounterMaxDayHistory(1); // 新增JMX远程配置 mqConfig.setJMXManagementEnabled(true); mqConfig.setJMXRemoteManagementEnabled(true); // 关键:开启远程JMX mqConfig.setRMIRegistryPort(1099); // RMI注册中心端口 mqConfig.setRMIServerPort(1098); // RMI服务器端口(需与注册端口不同) mqConfig.setManagementAddress("localhost"); mqConfig.setManagementNotificationAddress("localhost"); server.setConfiguration(mqConfig); server.start();
2. 配置Java 17的RMI系统属性
Java 17对RMI连接的主机名解析有严格限制,需在测试启动前设置以下系统属性(可在代码中设置,或通过测试启动参数传递):
// 在启动EmbeddedActiveMQ之前添加 System.setProperty("java.rmi.server.hostname", "localhost"); System.setProperty("com.sun.management.jmxremote.authenticate", "false"); System.setProperty("com.sun.management.jmxremote.ssl", "false");
3. 避免Spring Boot 3.x的JMX自动配置冲突
Spring Boot 3.x默认会启用自身的JMX配置,可能占用1099端口,导致Artemis的RMI注册中心无法启动。解决方式二选一:
- 禁用Spring Boot的JMX自动配置:在测试类上添加注解:
@EnableAutoConfiguration(exclude = {JmxAutoConfiguration.class}) - 修改Spring Boot的JMX端口:在
application-test.properties中配置:spring.jmx.enabled=true spring.jmx.server.port=1100 # 与Artemis的1099端口错开
4. 正确的JMX连接与队列深度获取代码
修改JMX连接代码,确保使用正确的服务URL,并通过QueueControl MBean获取队列深度:
// 注意:如果修改了RMIServerPort,URL无需变更,注册中心会引导到正确的服务器端口 JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); // 队列的MBean名称格式:org.apache.activemq.artemis:broker=<brokerName>,component=addresses,address=<addressName>,subcomponent=queues,routing-type=<routingType>,queue=<queueName> // 嵌入式Artemis默认brokerName为"0",routingType默认"anycast"(点对点队列) ObjectName queueObjectName = new ObjectName("org.apache.activemq.artemis:broker=0,component=addresses,address=yourQueueAddress,subcomponent=queues,routing-type=anycast,queue=yourQueueName"); QueueControl queueControl = JMX.newMBeanProxy(mbsc, queueObjectName, QueueControl.class); // 获取队列深度(未消费消息数) long messageCount = queueControl.getMessageCount(); System.out.println("Queue depth: " + messageCount); jmxc.close();
关键注意事项
- 嵌入式Artemis的默认broker名称是
0,如果自定义了broker名称,需要在MBean名称中替换对应的broker=<yourBrokerName>。 - 队列的address名称需与创建队列时指定的address一致(Artemis中队列属于某个address)。
- 确保测试代码中Artemis服务器完全启动后,再发起JMX连接(可通过
server.waitForActivation()等待服务器就绪)。
内容的提问来源于stack exchange,提问作者user28089685
相关产品推荐
相关产品推荐

