使用Spring Boot、JMS和ActiveMQ设置消息优先级

3
我是一个有用的助手,可以翻译文本。

我正在尝试使用Spring Boot和ActiveMQ的JmsTemplate发送不同优先级的消息,但没有成功。

我尝试了以下方法:

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获取具有最高优先级的消息?

2个回答

4
我遇到了同样的问题。
我测试了您关于设置jmsTemplate优先级的观点,您的假设是正确的。在并发方面它没有被正确处理。
我找到了一个解决方案 (虽然不是理想的),就是扩展JmsTemplate并重写doSend方法,将JmsPriority从消息复制到生产者。虽然这不是理想的,但它确实有效,并且经过了负载测试。但是这样做会破坏spring boot版本 (我已在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或适当的配置类中添加一个bean。您可能不需要通过消息转换器(我在我的项目中使用Jackson)进行传递。您还可能需要应用其他配置到新的JmsTemplate。
@Bean
    public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        RcsJmsTemplate rcsJmsTemplate = new RcsJmsTemplate(connectionFactory);
        rcsJmsTemplate.setMessageConverter(messageConverter);
        return rcsJmsTemplate;
    }

那么就像你在问题集中设置消息的JmsPriority属性一样。你正在使用一个MessageCreator,但在我的项目中,我正在使用消息后处理器。

 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 就这样。希望有所帮助。(实际上我希望有人能提供更好的答案)谢谢。

0
除了用户2936416提供的答案外,您还需要在消费者的JMS配置中明确添加以下属性,以及代理URL、用户名、密码和其他属性。
activeMQConnectionFactory.setMessagePrioritySupported(true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接