Установите приоритет сообщения, используя Spring Boot, JMS и ActiveMq - PullRequest
0 голосов
/ 31 октября 2019

Я пытаюсь отправлять сообщения с другим приоритетом с помощью JmsTemplate, используя Spring Boot и ActiveMQ, и он не работает.

Я пробовал это:

MessageCreator mc = session -> {
    TextMessage tm = session.createTextMessage("hello");
    tm.setJMSPriority(6);
    return tm;
};
jmsTemplate.send((Queue) () -> "box", mc);

Приоритет внутри ActiveMQброкер по-прежнему равен 4 (значение по умолчанию).

Единственный способ найти приоритет для изменения приоритета сообщения - изменить приоритет на уровне JmsTemplate.

jmsTemplate.setPriority(3);

Проблема здесьтеперь все сообщения, отправленные после этого, будут иметь приоритет 3. Я знаю, что могу сбрасывать приоритет JmsTemplate после каждой отправки, но это не «чисто», а как насчет параллелизма?

Как установить приоритетдля каждого сообщения и получить сообщение с наивысшим приоритетом, используя @JmsListener?

1 Ответ

0 голосов
/ 12 ноября 2019

Я просто столкнулся с той же проблемой.

Я проверил вашу точку зрения об установке приоритета jmsTemplate, и ваше предположение верно. Это не обрабатывается должным образом с параллелизмом.

Решение, которое я нашел, что работает (хотя и не идеально), состоит в том, чтобы расширить JmsTemplate и переопределить метод doSend для копирования JmsPriority из сообщения производителю. Это не идеально, расширение класса make break на весенние загрузочные выпуски (я тестировал это на 2.1.7) и есть некоторые дополнительные шаги для регистрации нового JmsTemplate. Но это работает, и я протестировал его под нагрузкой.

Шаги .....

Создайте новый класс, расширяющий JmsTemplate, переопределяющий метод doSend, чтобы скопировать приоритет из сообщения

import java.io.Serializable;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import org.springframework.jms.core.JmsTemplate;

public class RcsJmsTemplate extends JmsTemplate implements Serializable {

    public RcsJmsTemplate() {
    }

    public RcsJmsTemplate(ConnectionFactory connectionFactory) {
        super(connectionFactory);
    }

    /**
     * Actually send the given JMS message.
     *
     * AF: EXTENDED TO COPY THE PRIORITY FROM THE MESSAGE TO THE PRODUCER
     *
     * @param producer the JMS MessageProducer to send with
     * @param message the JMS Message to send
     * @throws JMSException if thrown by JMS API methods
     */
    @Override
    protected void doSend(MessageProducer producer, Message message) throws JMSException {
        if (getDeliveryDelay() >= 0) {
            producer.setDeliveryDelay(getDeliveryDelay());
        }

        producer.send(message, getDeliveryMode(), message.getJMSPriority(), getTimeToLive());

    }
}

Добавить компонент (в ваш App.java или соответствующий класс конфигурации). Возможно, вам не нужно проходить через конвертер сообщений (я использую Джексона в моем проекте). Также могут быть другие конфигурации, которые вам нужноприменитесь к новому JmsTemplate.

@Bean
    public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        RcsJmsTemplate rcsJmsTemplate = new RcsJmsTemplate(connectionFactory);
        rcsJmsTemplate.setMessageConverter(messageConverter);
        return rcsJmsTemplate;
    }

Затем, как в вашем вопросе, установите атрибут JmsPriority сообщения. Вы используете MessageCreator, но в моем проекте я использую сообщение post processoe

 public void convertAndSendWithPriority(JmsTemplate jmsTemplate, String destination, Object message, int priority) {
        jmsTemplate.convertAndSend(destination, message, (Message jmsMessage) -> {
            jmsMessage.setJMSPriority(priority);
            return jmsMessage;
        });
    }

Для полноты вы должны добавить свойство: spring.jms.template.qos-enabled = true

Вот так,Надеюсь, это поможет (на самом деле, я надеюсь, что кто-то придумает лучший ответ) Спасибо

...