使用rabbitMQ的Spring amqp延迟消息传递

时间:2017-04-07 07:38:43

标签: spring rabbitmq amqp

我很难在Spring AMQP / Rabbit MQ中找到预定/延迟消息的方法,并在这里找到了解决方案。但我仍然有一个问题 关于Spring AMQP / Rabbit MQ,它无法接收任何消息。

我的来源如下:

@Configuration
public class AmqpConfig {

    @Bean  
    public ConnectionFactory connectionFactory() {  
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();  
        connectionFactory.setAddresses("172.16.101.14:5672");  
        connectionFactory.setUsername("admin");  
        connectionFactory.setPassword("admin"); 
        connectionFactory.setPublisherConfirms(true); 
        return connectionFactory;  
    }  


    @Bean  
    @Scope("prototype") 
    public RabbitTemplate rabbitTemplate() {  
        RabbitTemplate template = new RabbitTemplate(connectionFactory());  
        return template;  
    } 


    @Bean
    CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange("my-exchange", "x-delayed-message", true, false, args);
    }

    @Bean  
    public Queue queue() {  
        return new Queue("spring-boot-queue", true);   

    }  

    @Bean
    Binding binding(Queue queue, Exchange delayExchange) {
        return BindingBuilder.bind(queue).to(delayExchange).with("spring-boot-queue").noargs();
    }

    @Bean  
    public SimpleMessageListenerContainer messageContainer() {  
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());  
        container.setQueues(queue());  
        container.setExposeListenerChannel(true);  
        container.setMaxConcurrentConsumers(1);  
        container.setConcurrentConsumers(1);  
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); 

        container.setMessageListener(new ChannelAwareMessageListener() {  

            public void onMessage(Message message, Channel channel) throws Exception {  
                byte[] body = message.getBody();  
                System.err.println("receive msg : " + new String(body));  
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费  

            }  
        });  

        return container;  
    }  


}

@Component
public class Send implements RabbitTemplate.ConfirmCallback{

    private RabbitTemplate rabbitTemplate;  

    @Autowired  
    public Send(RabbitTemplate rabbitTemplate) {  
        this.rabbitTemplate = rabbitTemplate; 
        this.rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setMandatory(true);
    }  

    public void sendMsg(String content) {  

        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); 

        rabbitTemplate.convertAndSend("my-exchange", "", content, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setHeader("x-delay", 6000);
                return message;
            }
        },correlationId);

        System.err.println("delay message send ................");

    }

    /**  
     * 回调  
     */  
    @Override  
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {  

        System.err.println(" callback id :" + correlationData);  

        if (ack) {  
            System.err.println("ok");  
        } else {  
            System.err.println("fail:" + cause);  
        }  
    }  
}

是否有人可以提供帮助。

谢谢大家。

1 个答案:

答案 0 :(得分:2)

延迟消息传递与Spring amqp无关,它是一个驻留在您的代码中的库,因此库无法保存任何消息。您可以尝试两种方法:

旧方法: 在每个消息/队列(策略)中设置TTL(生存时间)标头,然后引入DLQ来处理它。一旦ttl过期,您的消息将从DLQ移动到主队列,以便您的侦听器可以处理它。

最新方法: 最近,RabbitMQ推出了 RabbitMQ延迟消息插件 ,使用它可以实现相同的功能,并且自RabbitMQ-3.5.8起支持此插件支持。

您可以使用x-delayed-message类型声明交换,然后使用自定义标头x-delay发布消息,以毫秒为单位表示消息的延迟时间。消息将在x延迟毫秒后传送到相应的队列

<强>详细信息: 要使用延迟消息传递功能,请使用x-delayed-message类型声明交换:

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("my-exchange", "x-delayed-message", true, false, args);

请注意,我们在路由部分下传递了一个名为x-delayed-type的额外标头。

我们宣布交换后,我们可以发布消息,提供一个标题告诉插件延迟消息的时间:

byte[] messageBodyBytes = "delayed payload".getBytes("UTF-8");
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("x-delay", 5000);
AMQP.BasicProperties.Builder props = new AMQP.BasicProperties.Builder().headers(headers);
channel.basicPublish("my-exchange", "", props.build(), messageBodyBytes);

byte[] messageBodyBytes2 = "more delayed payload".getBytes("UTF-8");
Map<String, Object> headers2 = new HashMap<String, Object>();
headers2.put("x-delay", 1000);
AMQP.BasicProperties.Builder props2 = new AMQP.BasicProperties.Builder().headers(headers2);
channel.basicPublish("my-exchange", "", props2.build(), messageBodyBytes2);

在上面的例子中,我们发布了两条消息,用x-delay标头指定延迟时间。对于这个例子,插件将首先向我们的队列传递消息,其中包含正文&#34;更多延迟的有效负载&#34;然后是身体的那个&#34;延迟有效载荷&#34;。

如果x-delay标头不存在,那么插件将继续无延迟地路由消息。

更多信息:git