【RabbitMQ】TTL、DLX、延迟队列

目录

TTL:过期时间

1.设置消息的TTL

a.通过队列来设置消息的TTL

b.对消息进行单独设置TTL

两种方式比较

2.设置队列的TTL

DLX:死信队列

延迟队列

 


TTL:过期时间

Time to Live,过期时间。可以对消息和队列设置过期时间

2种方式设置过期时间:

  1. 通过队列属性设置,队列中所有消息都有相同的过期时间
  2. 对消息本身进行单独设置,每条消息的TTL 可以不同

如果两种方法一起使用,则消息的TTL以两者之间较小的那个数值为准。

消息在队列中的生存时间一旦超过设置的TTL值时,就会变成死信。

1.设置消息的TTL

a.通过队列来设置消息的TTL

这种方式是在channel.queueDeclare(),队列声明的时候设置x-message-ttl参数来实现单位是:毫秒   。当然可以通过Policy和HTTP API接口设置。

Map<String,Object> ars = new HashMap<>();
ars.put("x-message-ttl",1000);
channel.queueDeclare("queueName",true,false,false,ars);

 如果不设置TTL,那么此消息就不会过期,如果将TTL设置为0,则表示此时可以直接将消息投递给消费者,否则该消息将被丢失,这种方式可以代替immediate参数,(immediate参数在投递失败时会调用Basic.Return将消息返回),这个功能通过死信队列返回这个失败的消息。

一旦消息过期,就会从队列中抹去

b.对消息进行单独设置TTL

通过channel.basicPublish()方法实现,通过加入expiration的属相参数。单位:毫秒,同样可以通过HTTP API接口设置; 如下代码:   

   channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,
                new AMQP.BasicProperties().builder()
                    .deliveryMode(2)   //设置为持久化
                    .expiration("60000") //设置为1分钟的过期时间
                .build(),message.getBytes());

即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期是在即将投递到消费者之前判定的。

两种方式比较

第一种方式:

一旦消息过期,就会从队列中抹去

第二种方式:

即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期是在即将投递到消费者之前判定的。

 为什么这两种方法处理的方式不一样?

因为第一种方法里,队列中己过期的消息肯定在队列头部,RabbitMQ只要定期从队头开始扫描是否有过期的消息即可。而第二种方法里,每条消息的过期时间不同,如果要删除所有过期消息势必要扫描整个队列,所以不如等到此消息即将被消费时再判定是否过期,如果过期再进行删除即可。

2.设置队列的TTL

  通过channel.queueDeclare方法中的x-expires参数可以控制队列被自动删除前处于未使用状态的时间。未使用的意思是队列上没有任何的消费者,队列也没有被重新声明,并且在过期时间段内也未调用过Basic.Get命令。

      设置队列里的TTL可以应用于类似RPC方式的回复队列,在RPC中,许多队列会被创建出来,但是却是未被使用的。RabbitMQ会确保在过期时间到达后将队列删除,但是不保障删除的动作有多及时。在RabbitMQ重启后,持久化的队列的过期时间会被重新计算。

         用于表示过期时间的x-expires参数以毫秒为单位,井且服从和x-message-ttl一样的约束条件,不过不能设置为0。比如该参数设置为1000,则表示该队列如果在1秒钟之内未使用则会被删除。

   代码如下:         

Map<String,Object> ars = new HashMap<>();
ars.put("x-expires",1000);
channel.queueDeclare("queueDemo",true,false,false,ars);

DLX:死信队列

DLX,全称为Dead-Letter-Exchange,可以称之为死信交换器,也有人称之为死信邮箱。当消息在一个队列中变成死信( dead message )后,它能被重新被发送到另一个交换器中,这个交换器就是DLX,绑定DLX的队列就称之为死信队列。

消息变成死信一般是由于以下几种情况:

  • 消息被拒绝(Basic.Reject/Basic.Nack),并且设置requeue参数为fa l s e
  •  消息过期;
  • 队列达到最大长度。

通过在channel.queueDeclare方法中设置x-dead-letter-exchange参数来为这个队列添加DLX。

channel.exchangeDeclare("dlx_exchange","direct");
Map<String,Object> ars= new HashMap<>();
ars.put("x-dead-letter-message","dlx_exchange");
//为队列添加DLX
channel.queueDeclare("myQueue",false,false,false,ars);
//也可以为这个DLX指定路由键,如果没有特殊指定,则使用原队列的路由键
//ars.put("x-dead-letter-routing-key","dlx-routing-key");

对于RabbitMQ来说,DLX是一个非常有用的特性。它可以处理异常情况下,消息不能够被消费者正确消费(消费者调用了Basic.Nack或者Basic.Reject)而被置入死信队列中的情况,后续分析程序可以通过消费这个死信队列中的内容来分析当时所遇到的异常情况,进而可以改善和优化系统。DLX配合TTL使用还可以实现延迟队列的功能.

channel.exchangeDeclare("exchange.dlx","direct" ,true);
channel.exchangeDeclare("exchange.normal", "fanout",true);
Map <String , Object>  args  =  new  HashMap <String, Object>( );
args.put("x-message-ttl",  10000);
args.put("x-dead-letter-ex change"," exchange.dlx ");
args.put("x-dead-letter-routing-key ", "routingkey");
channe1.queueDec1are("queue.norma1", true, fa1se, fa1se, args);
channe1.queueBind("queue.normal",  " exchange.normal", "");
channe1.queueDec1are("queue.d1x",true,false,false, null) ;
channel.queueBind("queue.dlx","exchange.dlx", "routingkey");
channel.basicPublish("exchange.normal", "rk",
MessageProperties.PERSISTENT_TEXT_PLAIN, "dlx".getBytes()) ;

延迟队列

延迟队列存储的对象是对应的延迟消息,所谓"延迟消息"是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

 延迟队列的使用场景有很多,比如:

  • 在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果3 0分钟内没有支付成功,那么这个订单将进行异常处理,这时就可以使用延迟队列来处理这些订单了。
  • 用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作。这时候就可以将用户指令发送到延迟队列,当指令设定的时间到了再将指令推送到智能设备。

AMQP协议中,或者R a b b i t M Q本身没有直接支持延迟队列的功能,但是可以通过前面所介绍的DLX和TTL模拟出延迟队列的功能。

对于queue.dlx这个死信队列来说,同样可以看作延迟队列。假设一个应用中需要将每条消息都设置为10秒的延迟,生产者通过exchange.nomal这个交换器将发送的消息存储在queue.nomal这个队列中。消费者订阅的并非是queue.nomal这个队列,而是queue.dlx这个队列。当消息从queue.nomal这个队列中过期之后被存入queue.dlx这个队列中,消费者就恰巧消费到了延迟1 0秒的这条消息。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值