1.检查是否安装延时插件 : rabbitmq_delayed_message_exchange
rabbitmq-plugins list
若没有就去下载 https://www.rabbitmq.com/community-plugins.html
2.将下载的插件上传到 rabbit 下 plugins 目录中
3.安装插件 : rabbitmq-plugins enable rabbitmq_delayed_message_exchange
4.什么是延时队列?
队列 : 先进先出
延时队列中的元素在指定的时间被消费
场景 : 订单在下单后十分钟没有支付自动取消
TTL(Time To Live): 消息或者该队列中的所有消息的最大存活时间,单位毫秒(ms),可以给消息或者队列设置
如果同时配置了队列的TTL和消息的TTL,那么较小的那个值将会被使用。
5.创建 Spring boot 项目导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>${spring.version}</version>
</dependency>
6.创建配置类
package rabbit;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
- * @Classname LiuYin
- * @Date 2020/9/2 14:05
* @Description
*/
@Configuration
public class RabbitDelayConfig {
/**
* 立即消费的队列名称 消费消息是需指定队列名称
*/
public static final String IMMEDIATE_QUEUE_XDELAY = "queue.order.immediate";
/**
* 延时的交换器名称 发送消息时会指定交换器
*/
public static final String DELAYED_EXCHANGE = "exchange.order.delayed";
/**
* 路由key名称 发送消息时会指定路由
*/
public static final String ROUTING_KEY = "routing.order.key";
/**
* 创建立即消费队列
* @return
*/
@Bean
public Queue immediateQueue() {
// 第一个参数是创建的队列名称,第二个参数是是否支持持久化
return new Queue(IMMEDIATE_QUEUE_XDELAY, true);
}
/**
* 在message到达Exchange后,Exchange会根据route规则进入对应的Queue中,message可能进入一个Queue也可能进入对应多个Queue
* @return
*/
@Bean
public CustomExchange delayExchange() {
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
}
/**
* 把立即消费的队列和延时消费的exchange绑定在一起
* @return
*/
@Bean
public Binding bindingNotify() {
return BindingBuilder.bind(immediateQueue()).to(delayExchange()).with(ROUTING_KEY).noargs();
}
}
7.创建生产者
package rabbit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
/**
* @Classname LiuYin
* @Date 2020/9/2 14:15
* @Description
*/
@Component
public class RabbitDelaySender {
private static final Logger LOGGER = LoggerFactory.getLogger(RabbitDelaySender.class);
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg, int delayTime) {
LOGGER.info("订单号: " + msg + " 加入延时队列 定时(ms): " + delayTime);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
this.rabbitTemplate.convertAndSend(RabbitDelayConfig.DELAYED_EXCHANGE, RabbitDelayConfig.ROUTING_KEY, msg, message -> {
//给消息设置存活时间
message.getMessageProperties().setDelay(delayTime);
// LOGGER.info(sdf.format(new Date()) + " Delay sent.");
return message;
});
}
}
8.创建消费者
package rabbit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Classname LiuYin
* @Date 2020/9/2 14:17
* @Description
*/
@Component
@EnableRabbit
@Configuration
public class RabbitDelayReceiver {
private static final Logger LOGGER = LoggerFactory.getLogger(RabbitDelayReceiver.class);
@RabbitListener(queues = RabbitDelayConfig.IMMEDIATE_QUEUE_XDELAY)
public void get(String msg) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOGGER.info("收到失效订单: " + msg + " 时间:" + sdf.format(new Date()));
}
}
9.创建测试API
package rabbit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Classname LiuYin
* @Date 2020/9/2 14:20
* @Description
*/
@RestController
public class RabbitMQController {
@Autowired
private RabbitDelaySender rabbitdelaySender;
@GetMapping("/testRabbit1")
public void testRabbit1(@RequestParam String orderId) {
rabbitdelaySender.send(orderId, 5000);//5秒
}
@GetMapping("/testRabbit2")
public void testRabbit2(@RequestParam String orderId) {
rabbitdelaySender.send(orderId, 10000);//10秒
}
}
10.启动后,访问两个接口
11.第一次启动会报错 : no exchange 'xxx' in vhost,去网站里面添加 exchange, name填写 xchange.order.delayed