Кластер EAP 7 JMS не синхронизирован. Запланированное сообщение JMS заблокировано, когда узел не работает

Я настраиваю кластер EAP 7 в автономном режиме. Я выполнил это руководство и настроил свой кластер.

Затем я начал тестировать систему JMS с помощью простого приложения JMS. Каждый раз, когда я отправляю сообщение JMS, я замечаю, что счетчик сообщений JMS обновляется только в одном из узлов (вместо обоих узлов, показанных на видео). Общее количество отправленных сообщений равно сумме подсчетов от обоих узлов.

Однако, поскольку узлы сгруппированы в кластеры, я бы ожидал, что статистика JMS будет синхронизирована (что показано на видео), поэтому оба узла должны отображать общее количество сообщений, полученных в кластере, а не только их часть.

Кроме того, при отправке запланированного сообщения, если узел содержит сообщение dies, сообщение блокируется до перезапуска мертвого узла. Это определенно неприемлемо, поскольку я ожидал, что запланированное сообщение будет доставлено другим (работающим) узлом.

Все тесты выполняются с использованием стандартного файла standalone-full-ha.xml.

Вот все шаги, чтобы воспроизвести проблему:

Настройка среды

  1. Загрузите eap7.1 / 7.2 или wildfly12 / 14 и распакуйте в каталог
  2. переименуйте каталог в my-dir-node1
  3. скопируйте your-dir-node1 в my-dir-node2
  4. Update the configuration
    1. go to my-dir-node1/standalone and copy standalone-full-ha.xml to 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>

person Kobe Lin    schedule 13.06.2019    source источник


Ответы (1)


Вы неправильно понимаете кластер обмена сообщениями в EAP (и видео, на которое вы указали ссылку). Если вы отправляете 1 сообщение в кластер обмена сообщениями в EAP, только 1 узел в кластере имеет это сообщение. Сообщения не реплицируются между всеми узлами кластера. Статистика JMS для каждого узла в кластере не обязательно будет синхронизирована.

То, что вы видите, на самом деле является ожидаемым поведением. Кроме того, это то, что показано в видео, на которое вы указали ссылку. В видео клиентское приложение отправляет 2 сообщения при каждом запуске. Одно сообщение отправляется одному узлу кластера, а второе сообщение - другому узлу кластера. Вот почему метрика «Сообщения добавлены» на каждом узле увеличивается и кажется синхронизированной. Показатель «Добавленные сообщения» на каждом узле увеличивается на 1, когда отправляются 2 сообщения (1 + 1 = 2). Общее количество сообщений, добавленных в очереди в кластере, можно определить, суммируя «Сообщения, добавленные» от каждого узла в кластере.

Это поведение важно понимать, потому что оно означает, что если узел в кластере выходит из строя, все сообщения на этом узле становятся недоступными (как вы заметили). Если вы хотите, чтобы сообщения были доступны в случае отказа узла, вам необходимо настроить пару «активный / резервный». Дополнительную информацию см. В документации EAP. подробности о том, как это сделать.

person Justin Bertram    schedule 16.06.2019