使用Spring Boot,JMS和ActiveMq设置消息优先级

时间:2019-10-31 10:50:40

标签: spring-boot spring-jms jmstemplate

我正在尝试使用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获取优先级最高的邮件?

1 个答案:

答案 0 :(得分:0)

我只是遇到了同样的问题。

我测试了您关于设置jmsTemplate优先级的观点,您的假设是正确的。并发处理不正确。

我发现可行(虽然不理想)的解决方案是扩展JmsTemplate并重写doSend方法,以将JmsPriority从消息复制到生产者。这不是理想的选择,它扩展了Spring Boot发行版中的make类突破(我已经在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());

    }
}

添加一个bean(到您的App.java或适当的配置类中)您可能不需要通过消息转换器(我在项目中使用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

就这样。希望能帮助到你 (实际上,我希望有人能提供更好的答案) 谢谢

相关问题