EAP 7 JMS 集群不同步。节点关闭时计划的 JMS 消息被阻止
EAP 7 JMS cluster not in sync. Scheduled JMS message blocked when node is down
我正在以独立模式设置 EAP 7 集群。我按照 this tutorial 设置了我的集群。
然后我开始用一个简单的 JMS 应用程序测试 JMS 系统。每次发送 JMS 消息时,我都会观察到 JMS 消息计数仅在一个节点(而不是视频中显示的两个节点)中更新。发送的消息总数等于来自两个节点的计数之和。
但是,由于节点是集群的,我希望 JMS 统计信息是同步的(如视频所示),因此两个节点都应该显示集群中收到的消息总数,而不是仅显示部分消息他们。
另外,在发送定时消息时,如果持有消息的节点挂掉,则消息会被阻塞,直到挂掉的节点重启。这绝对是不可接受的,因为我希望预定消息由另一个 (运行) 节点传递。
所有测试都使用默认的 standalone-full-ha.xml
以下是重现问题的所有步骤:
环境设置
- 下载eap7.1/7.2或wildfly12/14解压到一个目录
- 将目录重命名为 my-dir-node1
- 将 your-dir-node1 复制到 my-dir-node2
- 更新配置
- 转到my-dir-node1/standalone并将standalone-full-ha.xml复制到standalone-full-ha-test.xml
- 编辑my-dir-node1/standalone/standalone-full-ha-test.xml
- 将 name="node1" 添加到根元素:
<server xmlns="urn:jboss:domain:5.0" name="node1">
- 搜索
<cluster password="${jboss.messaging.cluster.password:CHANGE ME!!}"/>
并将其替换为 <cluster password="${jboss.messaging.cluster.password:mypassword}"/>
- 在
<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
之后添加<jms-queue name="JMSTest" entries="java:/jms/queue/test"/>
- 转到my-dir-node2/standalone并重复上述步骤。确保将其命名为服务器 "node2" 而不是 "node1"
通过将 test-jms.war 复制到 my-dir-node1/standalone/deploy 和 your-dir-node2/standalone/deploy
来部署测试应用
我的测试应用程序的内容
<%@ page import="javax.naming.InitialContext" %>
<%@ page import="javax.jms.*" %>
<%@ page import="java.util.logging.Logger" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Logger logger = Logger.getLogger("JMSSender");
InitialContext initialContext = new InitialContext();
ConnectionFactory factory = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
Destination destination = (Destination)initialContext.lookup("java:/jms/queue/test");
Connection connection = factory.createConnection();
Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session1.createProducer(destination);
String body = request.getParameter("message");
if (body == null)
body = "Hello World!";
TextMessage message = session1.createTextMessage(body);
String delay = request.getParameter("delay");
if (delay != null)
message.setJMSDeliveryTime(System.currentTimeMillis() + Integer.parseInt(delay));
messageProducer.send(message);
logger.info("Send message: " + body);
%>
<html>
<head>
<title>Test JMS Sender</title>
</head>
<body>
<h1>Message</h1>
<p><strong><%=body%></strong></p>
<p>Add ?message=xxx to the url to change the message.</p>
<p>Add ?delay=xxx to the url to schedule a delivery at a later time. The unit of delay is in millisecond. ie: 1 second = 1000 </p>
</body>
</html>
JMS 接收方:
import org.apache.log4j.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(mappedName = "testQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
, @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
, @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/test")
})
public class JMSReceiver implements MessageListener {
// Logger for the class
private static Logger logger = Logger.getLogger(JMSReceiver.class.getName());
@Override
public void onMessage(Message message) {
TextMessage t = (TextMessage) message;
try {
logger.info(t.getText());
} catch (JMSException e) {
logger.info(e.getMessage());
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
您对 EAP 中的消息集群(以及您链接的视频)的理解不正确。如果您将 1 消息发送到 EAP 中的消息集群,集群中只有 1 节点有该消息。消息不会在集群中的所有节点之间复制。集群中每个节点的 JMS 统计信息 不一定 同步。
您所看到的实际上是预期的行为。此外,这是您链接的视频中演示的内容。在视频中,客户端应用程序在每次 运行 时发送 2 条消息。一条消息发送到一个集群节点,第二条消息发送到另一个集群节点。这就是为什么每个节点上的 "Messages Added" 指标增加并且看起来同步的原因。当发送 2 条消息 (1+1=2) 时,每个节点上的 "Messages Added" 指标增加 1。添加到集群中队列的消息总数可以通过对集群中每个节点的 "Messages Added" 求和来确定。
了解此行为很重要,因为这意味着如果集群中的某个节点出现故障,则该节点上的所有消息都将变得不可用(如您所见)。如果您希望消息在节点故障的情况下可用,那么您需要配置一个 live/backup 对。有关如何完成此操作的更多详细信息,请参阅 EAP documentation。
我正在以独立模式设置 EAP 7 集群。我按照 this tutorial 设置了我的集群。
然后我开始用一个简单的 JMS 应用程序测试 JMS 系统。每次发送 JMS 消息时,我都会观察到 JMS 消息计数仅在一个节点(而不是视频中显示的两个节点)中更新。发送的消息总数等于来自两个节点的计数之和。
但是,由于节点是集群的,我希望 JMS 统计信息是同步的(如视频所示),因此两个节点都应该显示集群中收到的消息总数,而不是仅显示部分消息他们。
另外,在发送定时消息时,如果持有消息的节点挂掉,则消息会被阻塞,直到挂掉的节点重启。这绝对是不可接受的,因为我希望预定消息由另一个 (运行) 节点传递。
所有测试都使用默认的 standalone-full-ha.xml
以下是重现问题的所有步骤:
环境设置
- 下载eap7.1/7.2或wildfly12/14解压到一个目录
- 将目录重命名为 my-dir-node1
- 将 your-dir-node1 复制到 my-dir-node2
- 更新配置
- 转到my-dir-node1/standalone并将standalone-full-ha.xml复制到standalone-full-ha-test.xml
- 编辑my-dir-node1/standalone/standalone-full-ha-test.xml
- 将 name="node1" 添加到根元素:
<server xmlns="urn:jboss:domain:5.0" name="node1">
- 搜索
<cluster password="${jboss.messaging.cluster.password:CHANGE ME!!}"/>
并将其替换为<cluster password="${jboss.messaging.cluster.password:mypassword}"/>
- 在
<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
之后添加 - 转到my-dir-node2/standalone并重复上述步骤。确保将其命名为服务器 "node2" 而不是 "node1"
<jms-queue name="JMSTest" entries="java:/jms/queue/test"/>
通过将 test-jms.war 复制到 my-dir-node1/standalone/deploy 和 your-dir-node2/standalone/deploy
来部署测试应用我的测试应用程序的内容
<%@ page import="javax.naming.InitialContext" %>
<%@ page import="javax.jms.*" %>
<%@ page import="java.util.logging.Logger" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Logger logger = Logger.getLogger("JMSSender");
InitialContext initialContext = new InitialContext();
ConnectionFactory factory = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
Destination destination = (Destination)initialContext.lookup("java:/jms/queue/test");
Connection connection = factory.createConnection();
Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session1.createProducer(destination);
String body = request.getParameter("message");
if (body == null)
body = "Hello World!";
TextMessage message = session1.createTextMessage(body);
String delay = request.getParameter("delay");
if (delay != null)
message.setJMSDeliveryTime(System.currentTimeMillis() + Integer.parseInt(delay));
messageProducer.send(message);
logger.info("Send message: " + body);
%>
<html>
<head>
<title>Test JMS Sender</title>
</head>
<body>
<h1>Message</h1>
<p><strong><%=body%></strong></p>
<p>Add ?message=xxx to the url to change the message.</p>
<p>Add ?delay=xxx to the url to schedule a delivery at a later time. The unit of delay is in millisecond. ie: 1 second = 1000 </p>
</body>
</html>
JMS 接收方:
import org.apache.log4j.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(mappedName = "testQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
, @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
, @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/test")
})
public class JMSReceiver implements MessageListener {
// Logger for the class
private static Logger logger = Logger.getLogger(JMSReceiver.class.getName());
@Override
public void onMessage(Message message) {
TextMessage t = (TextMessage) message;
try {
logger.info(t.getText());
} catch (JMSException e) {
logger.info(e.getMessage());
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
您对 EAP 中的消息集群(以及您链接的视频)的理解不正确。如果您将 1 消息发送到 EAP 中的消息集群,集群中只有 1 节点有该消息。消息不会在集群中的所有节点之间复制。集群中每个节点的 JMS 统计信息 不一定 同步。
您所看到的实际上是预期的行为。此外,这是您链接的视频中演示的内容。在视频中,客户端应用程序在每次 运行 时发送 2 条消息。一条消息发送到一个集群节点,第二条消息发送到另一个集群节点。这就是为什么每个节点上的 "Messages Added" 指标增加并且看起来同步的原因。当发送 2 条消息 (1+1=2) 时,每个节点上的 "Messages Added" 指标增加 1。添加到集群中队列的消息总数可以通过对集群中每个节点的 "Messages Added" 求和来确定。
了解此行为很重要,因为这意味着如果集群中的某个节点出现故障,则该节点上的所有消息都将变得不可用(如您所见)。如果您希望消息在节点故障的情况下可用,那么您需要配置一个 live/backup 对。有关如何完成此操作的更多详细信息,请参阅 EAP documentation。