RabbitMQ 延时消息队列

一、前言

 

       在做商城项目的过程中,遇到了这样一个问题:

       订单要在30分钟内未支付的情况下系统自动关闭此订单。当时考虑了三种方案:

       ①写一个定时任务去轮询

       ②在触发点开线程进行调度

       ③使用rabbitmq建立延时队列

 

        使用第一种如果对时间要求过高,对数据库压力比较大,使用第二种如果在线程开启后,用户付完款,该订单的线程又不能主动释放。白白占用线程,而刚好我们这个项目有使用rabbitmq做消息队列,于是最后使用mq在做延时队列。

 

 

二、实现

       

         对于第一种实现方案比较简单: 使用

1 //秒 分 时 日 月 年/星期
2 @Scheduled(cron = "0/1 * * * * ?") 
3 public void task() {
4        ......
5 }

        

         对于第二种方案:

        

   

 

 

        RabbitMQ:

        RabbitMQConfiguration查看之前的:RabbitMQ 消息发送、消息监听

 1 @Service
 2 public class AmqpTask {
 3 
 4     private static Logger logger = LoggerFactory.getLogger(AmqpTask.class);
 5     //30分钟
 6     private static final Integer time = 1000 * 60 * 1 * 30;
 7     //设置 DLX
 8     private static final String x_dead_letter_exchange = "amq.direct";
 9     //设置 routing  key 用于 DLX 分发消息
10     private static final String x_dead_letter_routing_key = "message_ttl_routingKey";
11 
12     @Autowired
13     private RabbitMQConfiguration rabbitMQConfiguration;
14 
15     /**
16      * @param message 发送的延时消息
17      * @throws IOException
18      */
19     public void task(String message) {
20         ConnectionFactory factory = new ConnectionFactory();
21         factory.setHost(rabbitMQConfiguration.getHost());
22         factory.setUsername(rabbitMQConfiguration.getUserName());
23         factory.setPassword(rabbitMQConfiguration.getPassword());
24         Connection connection = null;
25         Channel channel = null;
26         try {
27             connection = factory.newConnection();
28             channel = connection.createChannel();
29             HashMap<String, Object> arguments = new HashMap<>();
30             arguments.put("x-dead-letter-exchange", x_dead_letter_exchange);
31             arguments.put("x-dead-letter-routing-key", x_dead_letter_routing_key);
32             channel.queueDeclare(rabbitMQConfiguration.getOrderClosePublishQueueName(), true, false, false, arguments);
33             // 声明队列
34             channel.queueDeclare(rabbitMQConfiguration.getOrderCloseQueueName(), true, false, false, null);
35             // 绑定路由
36             channel.queueBind(rabbitMQConfiguration.getOrderCloseQueueName(), x_dead_letter_exchange, x_dead_letter_routing_key);
37             // 设置延时属性
38             AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
39             // 持久性 non-persistent (1) or persistent (2)
40             AMQP.BasicProperties properties = builder.expiration(String.valueOf(time)).deliveryMode(2).build();
41             // routingKey =delay_queue 进行转发
42             channel.basicPublish("", rabbitMQConfiguration.getOrderClosePublishQueueName(), properties, message.getBytes());
43             System.out.println("sent message: " + message + ",date:" + System.currentTimeMillis());
44             // 关闭频道和连接
45             channel.close();
46             connection.close();
47         } catch (IOException e) {
48             e.printStackTrace();
49             logger.error("IOException e:" + e.getMessage());
50         } catch (TimeoutException e) {
51             e.printStackTrace();
52             logger.error("TimeoutException e:" + e.getMessage());
53         }
54 
55     }

 

   

      

posted @ 2018-01-25 17:37  wanglittlehandsome  阅读(332)  评论(0编辑  收藏  举报