目前常见的应用软件都有新闻延迟推送的影子,其应用也极为广泛。比如淘宝七日内自动确认收货。我们签收货物后,物流系统会在7天后延迟给支付系统发消息,通知支付系统给商家打款。这个过程持续七天,就是利用了消息中间件的延时推送功能。12306机票支付确认页面。我们经常在选择投票点击确定跳转的页面有一个倒计时,也就是说如果30分钟内没有确认订单,订单会自动取消。实际上,在下订单的那一刻,票务业务系统会向订单系统发送延迟消息,延迟30分钟,告诉订单系统订单尚未完成。如果我们在30分钟内完成订单,我们可以通过逻辑代码判断。忽略收到的消息。在以上两种场景下,如果我们采用以下两种传统方案,无疑会大大降低系统的整体性能和吞吐量:使用redis为订单设置过期时间,最后判断订单是否还在redis已经完成。与消息延迟推送相比,这种方案性能较低,因为我们知道redis是存储在内存中的,当我们遇到恶意订单或者刷单的时候,会对内存造成巨大的压力。使用传统的数据库轮询来判断数据库表中订单的状态,无疑会增加IO次数,性能极低。使用jvm原生的DelayQueue也很占内存,而且没有持久化策略,当系统宕机或重启时,顺序信息会丢失。在RabbitMQ3.6.x之前,我们通常使用死信队列+TTL过期时间来实现延迟队列,这里不再过多介绍。从RabbitMQ3.6.x开始,RabbitMQ官方提供了延迟队列插件,下载后放在RabbitMQ根目录的plugins下。Image首先我们创建交换机和消息队列,application.properties中的配置和上一篇一样。导入org.springframework.amqp.core.*;导入org.springframework.context.annotation.Bean;导入org.springframework.context.annotation.Configuration;导入java.util.HashMap;导入java.util.Map;@Configurationpublic类MQConfig{publicstaticfinalStringLAZY_EXCHANGE=“Ex.LazyExchange”;publicstaticfinalStringLAZY_QUEUE="MQ.LazyQueue";publicstaticfinalStringLAZY_KEY="lazy.#";@BeanpublicTopicExchangelazyExchange(){//Mappros=newHashMap<>();//设置交换机制支持延迟消息推送//pros.put("x-delayed-message",'topic');TopicExchangeexchange=newTopicExchange(LAZY_EXCHANGE,true,false,pros);exchange.setDelayed(真);退换货;}@BeanpublicQueuelazyQueue(){返回新队列(LAZY_QUEUE,true);}@BeanpublicBindinglazyBinding(){返回BindingBuilder.bind(lazyQueue()).to(lazyExchange()).with(LAZY_KEY);}}我们在exchange的语句中,可以设置exchange.setDelayed(true)开启延迟队列,也可以在exchange的语句的方法中设置如下内容,因为第一个方法的底层是在这个实现的方法//Mappros=newHashMap<>();//设置开关支持延迟消息推送//pros.put("x-delayed-message","topic");TopicExchangeexchange=newTopicExchange(LAZY_EXCHANGE,true,false,pros);发送消息时,我们需要指定延迟推送时间。这里我们在发送消息的方法中传入参数newMessagePostProcessor()来获取Message对象,因为延迟时间需要借助Message对象的API来设置。导入com.anqi.mq.config.MQConfig;导入org.springframework.amqp.AmqpException;导入org.springframework.amqp.core.Message;导入org.springframework.amqp.core.MessageDeliveryMode;导入org.springframework.amqp.core.MessagePostProcessor;导入org.springframework.amqp.rabbit.connection.CorrelationData;导入org.springframework.amqp.rabbit.core.RabbitTemplate;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework.stereotype.Component;importjava.util.Date;@ComponentpublicclassMQSender{@AutowiredprivateRabbitTemplaterabbitTemplate;//confirmCallbackreturnCallback代码省略,请参看上一篇publicvoidsendLazy(Objectmessage){rabbitTemplate.setMandatory(true);rabbitTemplate.setConfirmCallback(confirmCallback);rabbitTemplate.setReturnCallback(returnCallback);//id+时间对局唯一CorrelationDatacorrelationData=newCorrelationData("12345678909"+newDate());//发送消息时指定header延迟延迟延迟延迟rabbittemplate.convertandsend(mqconfig.lazy_exchange,“lazy.boot”,messages,newMessagePostProcessor(){@overridepublicpublicMessagepostProcessMessage(postprocessMessage(messageMessage)(MessagedEliverymode.persistent);//message.getMessageProperties().setheader("X-delay“,“6000”);message.getMessageProperties()。setDelay(6000)(6000);returnmessage;returnmessage;returnmessage;returnmessage;recorlelationData);}}我们可以观察setDelay(Integeri)的底层代码,同样在header中设置了x-delay等同于我们手动设置headermessage.getMessageProperties().setHeader("x-delay","6000");/***设置x-delay标头。*@paramdelay延迟。*@since1.6*/publicvoidsetDelay(Integerdelay){if(delay==null||delay<0){this.headers.remove(X_DELAY);}else{this.headers.put(X_DELAY,delay);}}消费端进入消费importcom.rabbitmq.client.Channel;importorg.springframework.amqp.rabbit.annotation.*;importorg.springframework.amqp.support.AmqpHeaders;importorg.springframework.stereotype.Component;importjava...).getDeliveryTag();channel.basicAck(deliveryTag,true);System.out.println("延迟接收"+newString(msg.getBody()));}```##测试结果[#](https://www.cnblogs.com/haixiang/p/10966985.html#3724420099)导入org.junit.Test;导入org.junit.runner.RunWith;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework。boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;@SpringBootTest@RunWith(SpringRunner.class)publicclassMQSenderTest{@AutowiredprivateMQSendermqSender;@TestpublicvoidsendLazy()抛出Exception{Stringmsg="hellospringboot";mqSender.sendLazy(msg+":");}}果然在6秒后收到了消息`lazyreceivehellospringboot:`