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

使用rabbitMQ的Spring amqp延迟消息传递,spring,rabbitmq,amqp,Spring,Rabbitmq,Amqp,在Spring AMQP/Rabbit MQ中,我正在努力寻找计划/延迟消息的方法,并在这里找到了解决方案 关于Spring AMQP/Rabbit MQ,它无法接收任何消息 我的资料来源如下: @Configuration public class AmqpConfig { @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFa

在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);  
        }  
    }  
}
@配置
公共类AmqpConfig{
@豆子
公共连接工厂ConnectionFactory(){
CachingConnectionFactory connectionFactory=新的CachingConnectionFactory();
connectionFactory.setAddresses(“172.16.101.14:5672”);
connectionFactory.setUsername(“管理员”);
connectionFactory.setPassword(“管理员”);
connectionFactory.SetPublisherConfigrms(true);
返回连接工厂;
}  
@豆子
@范围(“原型”)
公共rabbitmplate rabbitmplate(){
RabbitTemplate=新的RabbitTemplate(connectionFactory());
返回模板;
} 
@豆子
CustomExchange延迟交换(){
Map args=new HashMap();
参数put(“x延迟类型”、“直接”);
返回新的CustomExchange(“我的exchange”、“x-delayed-message”、真、假、args);
}
@豆子
公用队列(){
返回新队列(“spring引导队列”,true);
}  
@豆子
绑定绑定(队列、交换延迟交换){
返回BindingBuilder.bind(queue).to(delayExchange).with(“spring引导队列”).noargs();
}
@豆子
公共SimpleMessageListenerContainer messageContainer(){
SimpleMessageListenerContainer容器=新的SimpleMessageListenerContainer(connectionFactory());
setQueues(queue());
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(1);
容器。setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(新ChannelAwareMessageListener(){
public void onMessage(消息消息,通道)引发异常{
byte[]body=message.getBody();
System.err.println(“接收消息:+新字符串(正文));
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false)//确认消息成功消费  
}  
});  
返回容器;
}  
}
@组成部分
公共类Send实现RabbitTemplate.ConfirmCallback{
私人兔样板兔样板;
@自动连线
公共发送(rabbitmplate rabbitmplate){
this.rabbitmplate=rabbitmplate;
this.rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setMandatory(true);
}  
public void sendMsg(字符串内容){
CorrelationData correlationId=新的CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(“我的交换”,内容,新消息后处理器(){
@凌驾
公共消息后处理消息(消息消息)引发AmqpException{
message.getMessageProperties().setHeader(“x-delay”,6000);
返回消息;
}
},correlationId);
System.err.println(“延迟消息发送”);
}
/**  
* 回调  
*/  
@凌驾
公共无效确认(CorrelationData CorrelationData,布尔值确认,字符串原因){
System.err.println(“回调id:+correlationData”);
如果(ack){
系统错误打印项次(“正常”);
}否则{
系统错误打印项次(“失败:+原因);
}  
}  
}
有没有人可以帮忙


谢谢大家。

延迟消息与Spring amqp无关,它是一个与您的代码一起驻留的库,因此该库不能保存任何这样的消息。您可以尝试两种方法:

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

最新方法: 最近RabbitMQ推出了RabbitMQ延迟消息插件,使用它您可以实现与RabbitMQ-3.5.8相同的插件支持

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

详细信息: 要使用延迟消息功能,请声明类型为x-delayed-message的exchange:

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("my-exchange", "x-delayed-message", true, false, args);
Map args=newhashmap();
参数put(“x延迟类型”、“直接”);
channel.ExchangeClare(“我的交换”、“x-delayed-message”、真、假、args);
请注意,我们传递了一个名为x-delayed-type的额外头,更多信息请参见Routing部分

声明exchange后,我们可以发布消息,提供一个标题,告诉插件消息延迟多长时间:

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);
byte[]messageBodyBytes=“延迟的有效负载”。getBytes(“UTF-8”);
Map headers=newhashmap();
标题。放置(“x延迟”,5000);
AMQP.BasicProperties.Builder props=新的AMQP.BasicProperties.Builder().headers(headers);
channel.basicPublish(“我的交换”,props.build(),messageBodyBytes);
byte[]messageBodyBytes2=“更多延迟的有效负载”。getBytes(“UTF-8”);
Map headers2=新的HashMap();
头2.放置(“x延迟”,1000);
AMQP.BasicProperties.Builder props2=新的AMQP.BasicProperties.Builder().headers(headers2);
channel.basicPublish(“我的交换”,props2.build(),messageBodyBytes2);
在上面的示例中,我们发布了两条消息,用x-delay头指定延迟时间。在本例中,插件将首先向队列发送正文为“more delayed payload”的消息,然后发送正文为“delayed payload”的消息