Wildfly 11独立模式下跨实例同主题JMS消息收发实现问询
实现Wildfly 11独立集群实例间的跨实例JMS主题消息收发
嘿,我来帮你搞定这个跨实例JMS消息收发的需求!结合你给出的Receiver代码片段,我整理了完整的实现步骤,从集群配置到代码完善,再到测试验证,一步一步来:
一、先搞定Wildfly集群基础配置
你已经用standalone-full-ha.xml启动实例了,这个配置文件默认已经开启了集群相关的功能,但得确保两个实例能互相发现并组成集群:
- 启动第一个实例(node1):
./standalone.sh -c standalone-full-ha.xml -Djboss.node.name=node1 -Djboss.socket.binding.port-offset=0 - 启动第二个实例(node2):
./standalone.sh -c standalone-full-ha.xml -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
这里用端口偏移避免两个实例的端口冲突,节点名称要唯一,启动后可以看日志,出现Joined cluster的字样就说明集群组建成功了。
接下来要确保主题topic/Blubb在两个实例中都能访问到,用Wildfly的CLI工具连接到任意一个实例,执行以下命令创建可跨实例访问的主题:
/subsystem=messaging-activemq/server=default/jms-topic=Blubb:add(entries=["java:/jms/topic/Blubb", "java:jboss/exported/jms/topic/Blubb"])
这个命令会创建两个JNDI入口,其中java:jboss/exported开头的是对外暴露的,方便跨实例访问。
二、完善你的Receiver(Message-Driven Bean)
你给出的Receiver代码已经有了基础框架,我帮你补全并加上集群相关的关键配置:
import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.inject.Named; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; @Named @MessageDriven( name = "TaskJmsMsgReceiver", activationConfig = { @ActivationConfigProperty( propertyName = "destinationLookup", propertyValue = "java:jboss/exported/jms/topic/Blubb" ), @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Topic" ), @ActivationConfigProperty( propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge" ), // 集群环境下必须加这个,让MDB能参与集群消费 @ActivationConfigProperty( propertyName = "cluster", propertyValue = "true" ) } ) public class TaskJmsMsgReceiver implements MessageListener { @Override public void onMessage(Message message) { if (message instanceof TextMessage) { try { String msgContent = ((TextMessage) message).getText(); // 打印当前节点名称,方便验证是哪个实例收到了消息 System.out.println("Receiver on node " + System.getProperty("jboss.node.name") + " got message: " + msgContent); } catch (JMSException e) { e.printStackTrace(); } } } }
几个关键点要注意:
- 用
java:jboss/exported/jms/topic/Blubb作为目标查找路径,这样另一个实例的Sender才能找到这个主题 cluster=true的配置是核心,确保这个MDB能在集群环境下接收消息,毕竟主题是发布订阅模式,两个实例的Receiver都应该收到消息- 打印节点名称是为了直观看到跨实例的效果
三、实现Sender组件(JMS Producer)
Sender可以做成一个CDI bean或者无状态EJB,我这里用CDI bean的方式,方便你和Receiver一起打包部署:
import javax.annotation.Resource; import javax.enterprise.context.RequestScoped; import javax.inject.Named; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; @Named @RequestScoped public class TaskJmsMsgSender { // 注入Wildfly默认的集群化连接工厂,支持跨实例通信 @Resource(mappedName = "java:/ConnectionFactory") private ConnectionFactory connectionFactory; // 注入我们创建的主题 @Resource(mappedName = "java:jboss/exported/jms/topic/Blubb") private Topic blubbTopic; public void sendMessage(String messageContent) { // 用try-with-resources自动关闭JMS资源,避免泄漏 try (Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(blubbTopic)) { TextMessage message = session.createTextMessage(messageContent); producer.send(message); System.out.println("Sender on node " + System.getProperty("jboss.node.name") + " sent message: " + messageContent); } catch (JMSException e) { e.printStackTrace(); } } }
这里的核心是用Wildfly默认的集群化连接工厂java:/ConnectionFactory,它已经配置好了跨实例的通信支持,不用额外折腾。
四、部署和测试
- 把Sender、Receiver和测试用的端点(如果需要)打包成WAR或者EAR包,分别部署到两个Wildfly实例上
- 我给你写个简单的REST端点来调用Sender,方便测试:
import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; @Path("/jms-test") public class JmsTestEndpoint { @Inject private TaskJmsMsgSender sender; @GET @Path("/send") public String sendTestMessage(@QueryParam("content") String content) { sender.sendMessage(content); return "Message sent successfully: " + content; } }
- 调用这个接口,比如访问
http://localhost:8080/your-app-name/jms-test/send?content=Hello Wildfly Cluster!,然后去两个实例的控制台看日志——你会看到两个Receiver都打印出收到的消息,这就说明跨实例的主题消息收发成功了!
五、一些踩坑提示
- 要是集群组建失败,检查两个实例的网络是否互通,或者看看Wildfly的集群配置(
standalone-full-ha.xml里的subsystem=jgroups部分)有没有问题 - 如果主题找不到,确认你用CLI创建主题的命令执行成功了,或者直接在
standalone-full-ha.xml里手动添加主题配置 - 集群环境下的消息可靠性:Wildfly的ActiveMQ Artemis集群默认支持消息复制,你可以测试关闭一个实例,发送消息后再重启,看看重启后的实例能不能收到消息,确保消息不会丢失
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

