EAP 7 JMS集群不同步。节点关闭时,计划的JMS消息被阻止

时间:2019-06-13 20:09:53

标签: jms jboss-eap-7 activemq-artemis

我正在以独立模式设置EAP 7集群。我跟随this tutorial并建立了我的集群。

然后,我开始使用简单的JMS应用程序测试JMS系统。每次发送JMS消息时,都会观察到JMS消息计数仅在一个节点(而不是视频中显示的两个节点)中更新。发送的消息总数等于两个节点的计数之和。

但是,由于节点是集群的,所以我希望JMS统计信息是同步的(如视频所示),因此,两个节点都应显示集群中接收到的消息总数,而不是它们中的一部分。

此外,在发送调度的消息时,如果该节点保留消息死亡,则该消息将被阻塞,直到死节点重新启动为止。这绝对是不可接受的,因为我希望预定的消息会由另一个(正在运行的)节点传递。

所有测试均使用默认的standalone-full-ha.xml

执行

这里是重现此问题的所有步骤:

环境设置

  1. 下载eap7.1 / 7.2或wildfly12 / 14并解压缩到目录
  2. 将目录重命名为my-dir-node1
  3. 将your-dir-node1复制到my-dir-node2
  4. 更新配置
    1. 转到my-dir-node1 / standalone,然后将standalone-full-ha.xml复制到standalone-full-ha-test.xml
    2. 编辑my-dir-node1 / standalone / standalone-full-ha-test.xml
    3. 将name =“ node1”添加到根元素:<server xmlns="urn:jboss:domain:5.0" name="node1">
    4. 搜索<cluster password="${jboss.messaging.cluster.password:CHANGE ME!!}"/>,并将其替换为<cluster password="${jboss.messaging.cluster.password:mypassword}"/>
    5. <jms-queue name="JMSTest" entries="java:/jms/queue/test"/>之后添加<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
    6. 转到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>

1 个答案:

答案 0 :(得分:0)

您对EAP中的消息传递群集(以及您链接的视频)的理解不正确。如果将 1 消息发送到EAP中的消息传递群集,则群集中唯一的 1 节点将收到该消息。消息不会在群集中的所有节点之间复制。集群中每个节点的JMS统计信息不必同步。

实际上,您看到的是预期的行为。此外,这是您链接的视频中演示的内容。在视频中,客户端应用程序每次运行时都会发送 2 消息。一个消息到达一个群集节点,第二个消息到达另一群集节点。这就是为什么每个节点上的“已添加邮件”度量标准都增加并且看起来是同步的原因。发送2条消息(1 + 1 = 2)后,每个节点上的“已添加消息”度量标准将增加1。可以通过将群集中每个节点的“已添加邮件”相加来确定添加到群集中队列中的邮件总数。

此行为很重要,因为这意味着如果集群中的某个节点发生故障,那么该节点上的所有消息将变得不可用(如您所观察到的)。如果希望在节点发生故障时消息可用,则需要配置实时/备份对。有关如何完成此操作的更多详细信息,请查阅EAP documentation