集群 WildFly 10 域消息传递
Clustered WildFly 10 domain messaging
我有三台机器位于不同的网络:
- 作为大师
- 作为节点 1
- 作为节点 2
在 as-master 中,我将 WildFly 作为域主机主机,这两个节点将 WildFly 作为域主机从机,每个节点都在 full-ha 服务器组中启动一个实例。从 as-master web 控制台我可以看到 full-ha 配置文件运行时中的两个节点,如果我部署 WAR 它会在两个节点上正确启动。
现在,我想要实现的是 WAR 的两个实例之间的消息传递,即从 as-node-1 中的生产者实例发送消息,所有节点中的消费者都应该收到消息。
这就是我的尝试:向 WildFly 添加了一个主题 domain.xml
:
<jms-topic name="MyTopic" entries="java:/jms/my-topic"/>
创建 JAX-RS 端点以触发绑定到主题的生产者:
@Path("jms")
@RequestScoped
public class MessageEndpoint {
@Inject
JMSContext context;
@Resource(mappedName = "java:/jms/my-topic")
Topic myTopic;
@GET
public void sendMessage() {
this.context.createProducer().send(this.myTopic, "Hello!");
}
}
创建一个MDB听题:
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destination",
propertyValue = "java:/jms/my-topic"
),
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Topic")
)
)
public class MyMessageListener implements MessageListener {
private final static Logger LOGGER = /* ... */
public void onMessage(Message message) {
try {
String body = message.getBody(String.class)
LOGGER.info("Received message: " + body);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
但是当我 curl as-node-1/jms
时,我只在 as-node-1 中看到日志,而当我 curl as-node-2/jms
时,我只在 as-node-2 中看到日志。
不应该在部署WAR的所有节点上传递消息吗?我错过了什么?
因为我提出了完全相同的问题 - 请将答案放在这里。
是的,如果目的地是主题,则消息应该传送到所有节点。
在默认配置下,ActiveMQ Artemis 使用广播来发现并连接到其他节点(在同一发现组中)上的其他 ActiveMQ 实例:
<discovery-group name="dg-group1" jgroups-channel="activemq-cluster"/>
<cluster-connection name="my-cluster" discovery-group="dg-group1" connector-name="http-connector" address="jms"/>
仍然需要确保 jms-topic 的 JNDI 名称以“jms”开头,以匹配上面一行中的 address="jms"
(可以在你的情况下:“java:/jms/my-topic
”)
您的示例中唯一遗漏的是让它在所有节点上运行:
<cluster password="yourPassword" user="activemqUser"/>
(肯定 activemqUser
用户必须更早添加,例如使用 addUser.sh 脚本)。
这让 ActiveMQ 实例可以相互通信。在节点之间创建所谓的 Core Bridge 连接。如 ActiveMQ manual 所述:
..this is done transparently behind the scenes - you don't have to
declare an explicit bridge for each node
如果一切正常,则可以在 server.log 中找到该桥:AMQ221027: Bridge ClusterConnectionBridge@63549ead [name=sf.my-cluster ...] is connected.
顺便说一句,如果目标是 Queue,则 ActiveMQ 不会将消息发送到其他节点,除非消息未在本地使用。
P.s。作为回答,这是指将事件分发到集群中所有节点的经典方法。
我有三台机器位于不同的网络:
- 作为大师
- 作为节点 1
- 作为节点 2
在 as-master 中,我将 WildFly 作为域主机主机,这两个节点将 WildFly 作为域主机从机,每个节点都在 full-ha 服务器组中启动一个实例。从 as-master web 控制台我可以看到 full-ha 配置文件运行时中的两个节点,如果我部署 WAR 它会在两个节点上正确启动。
现在,我想要实现的是 WAR 的两个实例之间的消息传递,即从 as-node-1 中的生产者实例发送消息,所有节点中的消费者都应该收到消息。
这就是我的尝试:向 WildFly 添加了一个主题 domain.xml
:
<jms-topic name="MyTopic" entries="java:/jms/my-topic"/>
创建 JAX-RS 端点以触发绑定到主题的生产者:
@Path("jms")
@RequestScoped
public class MessageEndpoint {
@Inject
JMSContext context;
@Resource(mappedName = "java:/jms/my-topic")
Topic myTopic;
@GET
public void sendMessage() {
this.context.createProducer().send(this.myTopic, "Hello!");
}
}
创建一个MDB听题:
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destination",
propertyValue = "java:/jms/my-topic"
),
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Topic")
)
)
public class MyMessageListener implements MessageListener {
private final static Logger LOGGER = /* ... */
public void onMessage(Message message) {
try {
String body = message.getBody(String.class)
LOGGER.info("Received message: " + body);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
但是当我 curl as-node-1/jms
时,我只在 as-node-1 中看到日志,而当我 curl as-node-2/jms
时,我只在 as-node-2 中看到日志。
不应该在部署WAR的所有节点上传递消息吗?我错过了什么?
因为我提出了完全相同的问题 - 请将答案放在这里。
是的,如果目的地是主题,则消息应该传送到所有节点。
在默认配置下,ActiveMQ Artemis 使用广播来发现并连接到其他节点(在同一发现组中)上的其他 ActiveMQ 实例:
<discovery-group name="dg-group1" jgroups-channel="activemq-cluster"/>
<cluster-connection name="my-cluster" discovery-group="dg-group1" connector-name="http-connector" address="jms"/>
仍然需要确保 jms-topic 的 JNDI 名称以“jms”开头,以匹配上面一行中的 address="jms"
(可以在你的情况下:“java:/jms/my-topic
”)
您的示例中唯一遗漏的是让它在所有节点上运行:<cluster password="yourPassword" user="activemqUser"/>
(肯定 activemqUser
用户必须更早添加,例如使用 addUser.sh 脚本)。
这让 ActiveMQ 实例可以相互通信。在节点之间创建所谓的 Core Bridge 连接。如 ActiveMQ manual 所述:
..this is done transparently behind the scenes - you don't have to declare an explicit bridge for each node
如果一切正常,则可以在 server.log 中找到该桥:AMQ221027: Bridge ClusterConnectionBridge@63549ead [name=sf.my-cluster ...] is connected.
顺便说一句,如果目标是 Queue,则 ActiveMQ 不会将消息发送到其他节点,除非消息未在本地使用。
P.s。作为回答