设置 MessageProducer 优先级对消息没有影响

Setting MessageProducer priority has no effect on messages

我有高优先级的消息需要处理,而不是低优先级的消息,但是在 MessageProducer 上设置优先级似乎没有影响,并且消息的使用顺序与它们发送到队列的顺序相同。

下面是我的代码:

package com.example.jms;

import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.ProducerCallback;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;

@SpringBootApplication
public class JmsPriorityApplication {

    private static final Logger logger= LoggerFactory.getLogger(JmsPriorityApplication.class);

    public static void main(String[] args) {

        // Launch the application
        ConfigurableApplicationContext context = SpringApplication.run(JmsPriorityApplication.class, args);

        JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
        // Send a message with a POJO - the template reuse the message converter
        System.out.println("Sending an email message.");

        jmsTemplate.execute("mailbox", new ProducerCallback<Object>() {

            @Override 
            public Object doInJms(Session session, MessageProducer producer) throws JMSException { 
                String text = "Hello this msg1";
                int priority=1;
                TextMessage message1 = session.createTextMessage(text);
                producer.send(message1, DeliveryMode.PERSISTENT, priority, 0);
                logger.info("{} sent with priority={}", text, priority);

                text = "Hello this msg2";
                priority=9;
                TextMessage message2 = session.createTextMessage(text);
                producer.send(message2, DeliveryMode.PERSISTENT, priority, 0);
                logger.info("{} sent with priority={}", text, priority);
                return null;
            }

        } );

    }


    @Bean
    public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all boot's default to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some of Boot's default if necessary.
        return factory;
    }

}

Receiver.java

package com.example.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Receiver {

    @JmsListener(destination = "mailbox", containerFactory = "myFactory")
    public void receiveMessage(String msg) {
        System.out.println("Received <" + msg + ">");
    }

}

下面是输出:

Sending an email message.
2019-02-05 17:42:44.161  INFO 7828 --- [           main] com.example.jms.JmsPriorityApplication   : Hello this msg1 sent with priority=1
2019-02-05 17:42:44.161  INFO 7828 --- [           main] com.example.jms.JmsPriorityApplication   : Hello this msg2 sent with priority=9
Received <Hello this msg1>
Received <Hello this msg2>

我原以为 msg2 会在 msg1 之前收到。我不确定我在这里错过了什么。注意:消费者在发送消息时处于活动状态。

由于在发送消息时消费者处于活动状态,因此几乎可以肯定代理在第二条消息到达代理之前将第一条消息分派给客户端。这意味着高优先级消息基本上没有时间抢占低优先级消息,因为客户端已经收到了低优先级消息。

一般来说,优先传递的想法只有在队列中有大量邮件时才有意义。对于您的测试,您应该在发送完所有消息之前不激活消费者(一项需要某种外部协调或手动干预的任务),或者增加消息量,以便优先传递可以在队列中累积足够多的消息真的发生了。