使用死信队列来实现延迟队列:
消息在延时队列中时间如果小于前面的队列等待时间也不会先执行,会按照队列的方式一个一个出队
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitExchangeConfig {
public RabbitExchangeConfig() {
}
/**
* 死信队列跟交换机类型没有关系 不一定为directExchange 不影响该类型交换机的特性.
*
* @return the exchange
*/
@Bean("deadLetterExchange")
public Exchange deadLetterExchange() {
return ExchangeBuilder.directExchange("DL_EXCHANGE").durable(true).build();
}
/**
* 声明一个死信队列.
* x-dead-letter-exchange 对应 死信交换机
* x-dead-letter-routing-key 对应 死信队列
*
* @return the queue
*/
@Bean("deadLetterQueue")
public Queue deadLetterQueue() {
Map<String, Object> args = new HashMap<>(2);
// x-dead-letter-exchange 声明 死信交换机
args.put("x-dead-letter-exchange", "DL_EXCHANGE");
// x-dead-letter-routing-key 声明 死信路由键
args.put("x-dead-letter-routing-key", "KEY_R");
return QueueBuilder.durable("DL_QUEUE").withArguments(args).build();
}
/**
* 定义死信队列转发队列.
*
* @return the queue
*/
@Bean("redirectQueue")
public Queue redirectQueue() {
return QueueBuilder.durable("REDIRECT_QUEUE").build();
}
/**
* 死信路由通过 DL_KEY 绑定键绑定到死信队列上.
*
* @return the binding
*/
@Bean
public Binding deadLetterBinding() {
return new Binding("DL_QUEUE", Binding.DestinationType.QUEUE, "DL_EXCHANGE", "DL_KEY", null);
}
/**
* 死信路由通过 KEY_R 绑定键绑定到死信队列上.
*
* @return the binding
*/
@Bean
public Binding redirectBinding() {
return new Binding("REDIRECT_QUEUE", Binding.DestinationType.QUEUE, "DL_EXCHANGE", "KEY_R", null);
}
}
import com.alibaba.fastjson.JSONObject;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.UUID;
@RestController
@RequestMapping("//Ticket")
public class Ticket2Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("/test")
public void test() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
MessagePostProcessor messagePostProcessor = message -> {
MessageProperties messageProperties = message.getMessageProperties();
// 设置编码
messageProperties.setContentEncoding("utf-8");
// 设置过期时间10*1000毫秒
messageProperties.setExpiration("60000");
return message;
};
JSONObject jsonObject= new JSONObject();
jsonObject.put("msg","第一个");
jsonObject.put("date", LocalDateTime.now());
// 向DL_QUEUE 发送消息 10*1000毫秒后过期 形成死信
rabbitTemplate.convertAndSend("DL_EXCHANGE", "DL_KEY", jsonObject.toJSONString(), messagePostProcessor, correlationData);
}
@PostMapping("/test2")
public void test2() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
MessagePostProcessor messagePostProcessor = message -> {
MessageProperties messageProperties = message.getMessageProperties();
// 设置编码
messageProperties.setContentEncoding("utf-8");
// 设置过期时间10*1000毫秒
messageProperties.setExpiration("2000");
return message;
};
JSONObject jsonObject= new JSONObject();
jsonObject.put("msg","第二个");
jsonObject.put("date", LocalDateTime.now());
// 向DL_QUEUE 发送消息 10*1000毫秒后过期 形成死信
rabbitTemplate.convertAndSend("DL_EXCHANGE", "DL_KEY", jsonObject.toJSONString(), messagePostProcessor, correlationData);
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@Slf4j
public class TestListener {
//2.10.0-C
@RabbitListener(queues = {"REDIRECT_QUEUE"})
public void message(Message message) {
log.info("监听的消息:{},接收时间为:{}", new String(message.getBody()), LocalDateTime.now());
}
}
监听的消息:{"msg":"第二个","date":"2020-08-14T15:54:04.508"},接收时间为:2020-08-14T15:54:59.857
监听的消息:{"msg":"第一个","date":"2020-08-14T15:53:59.841"},接收时间为:2020-08-14T15:54:59.857
利用RabbitMq插件实现延迟队列
下载rabbitmq_delayed_message_exchange插件,然后解压放置到RabbitMQ的插件目录
该插件的影响和限制
- 会降低性能,所以如果没有该需求,则不要使用。
- 该插件不适合大数据量的延时消息,比如百万或一亿。
- 延时时长:0<=n<=(2^32)-1 ,单位毫秒。
@Bean("delayExchange")
public Exchange delayExchange() {
Map<String, Object> args = new HashMap<>(1);
// x-delayed-type 声明 延迟队列Exchange的类型
args.put("x-delayed-type", "direct");
return new CustomExchange("DELAY_EXCHANGE", "x-delayed-message",true, false,args);
}
@Bean("delayQueue")
public Queue delayQueue() {
return QueueBuilder.durable("DELAY_QUEUE").build();
}
/**
* 将延迟队列通过routingKey绑定到延迟交换器
*
* @return
*/
@Bean
public Binding delayQueueBindExchange() {
return new Binding("DELAY_QUEUE", Binding.DestinationType.QUEUE, "DELAY_EXCHANGE", "DELAY_ROUTING_KEY", null);
}
import com.alibaba.fastjson.JSONObject;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.UUID;
@RestController
@RequestMapping("//Mq")
public class Ticket3Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("/test")
public void test() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
MessagePostProcessor messagePostProcessor = message -> {
MessageProperties messageProperties = message.getMessageProperties();
// 设置编码
messageProperties.setContentEncoding("utf-8");
// 设置过期时间10*1000毫秒
messageProperties.setDelay(60000);
return message;
};
JSONObject jsonObject= new JSONObject();
jsonObject.put("msg","第一个");
jsonObject.put("date", LocalDateTime.now());
// 向DL_QUEUE 发送消息 10*1000毫秒后过期 形成死信
rabbitTemplate.convertAndSend("DELAY_EXCHANGE", "DELAY_ROUTING_KEY", jsonObject.toJSONString(), messagePostProcessor, correlationData);
}
@PostMapping("/test2")
public void test2() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
MessagePostProcessor messagePostProcessor = message -> {
MessageProperties messageProperties = message.getMessageProperties();
// 设置编码
messageProperties.setContentEncoding("utf-8");
// 设置延迟毫秒
messageProperties.setDelay(20000);
return message;
};
JSONObject jsonObject= new JSONObject();
jsonObject.put("msg","第二个");
jsonObject.put("date", LocalDateTime.now());
// 向DL_QUEUE 发送消息 10*1000毫秒后过期 形成死信
rabbitTemplate.convertAndSend("DELAY_EXCHANGE", "DELAY_ROUTING_KEY", jsonObject.toJSONString(), messagePostProcessor, correlationData);
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@Slf4j
public class Test2Listener {
//2.10.0-C
@RabbitListener(queues = {"DELAY_QUEUE"})
public void message(Message message) {
log.info("监听的消息222:{},接收时间为:{}", new String(message.getBody()), LocalDateTime.now());
}
}
监听的消息222:{"msg":"第二个","date":"2020-08-14T17:49:21.200"},接收时间为:2020-08-14T17:49:41.215
监听的消息222:{"msg":"第一个","date":"2020-08-14T17:49:19.299"},接收时间为:2020-08-14T17:50:19.313
参考了一下