一. TTL 过期时间
- 消息TTL
ttl与网络包跳数超时原理一致, 消息在队列中生存的时间超过ttl,就会成为"死信" 消费者无法再接收处理该消息, 除非放入死信队列等进行转移处理
ttl设置方法:
-
设置队列属性, 那么队列中所有的消息都有相同的超时时间
设置方法为在queue declare声明定义的世行加入x-message-ttl进行设置 , 单位是毫秒
-
消息本身进行设置, 消息的超时时间不一样
(两个一起使用时,以ttl最小的那个为准)
设置方法, 在basicpublish的时候,设置expiration属性参数, 单位也为毫秒
队列属性设置ttl, 如果消息过期,则会直接从对列中丢弃,原因是,由于ttl一致, 又基本是FIFO的模式,那么过期消息一定在队列的头部。
对于消息本身设置ttl, 消息过期,不会马上丢弃,而是在消息进行投递的时候检查过期再丢弃, 这样1. 简单,维护成本低 2. 性能更好,不用实时扫描队列
不设置ttl, 则消息不会过期, 如果ttl为0, 除非消息直接投递给消费者,否则直接丢弃,这个就可以模拟之前的immediate消息处理, 但是immediate 会return消息给生产者,ttl直接丢弃,这里是区别
注: 如果rabbitmq在投递消息的时候发现消息队列为空,那么将会尝试将消息直接投递给消费者,而不用再进入消息队列进行处理
- 队列TTL
不仅消息有ttl, 队列也有ttl, 队列ttl, 设置方法是在queue declare中的x-expires参数控制队列未被使用的时间, 未使用: 没有消费者,没有被重新声明,没有调用过basic.get
rabbitmq会在队列过期后删除队列,但是不会是实时的, 对于持久化队列, 如果在过期后删除, 在重启后,过期的时间重新计算,不会被马上移除
二. DLX 死信队列 dead-letter-exchange
又叫: 死信交换机,死信邮箱等
当消息在一个队列中成为死信, 将会被发送到DLX死信交换, 绑定DLX的队列叫死信队列
死信:
- 消息被拒绝 (basic.reject/basic/nack)并设置requeue为false
- 消息过期
- 队列达到最大长度
死信交换机实际也是一个一般的交换机,只是它能在任何队列山被指定,通过设置某个队列的属性。
如果某个队列的消息过期,则会被发送到死信队列
与ttl配合可以模拟immedaite功能
设置方法: 在queue declare中设置x-dead-letter-exchane参数添加DLX
与普通交换机一样首先需要设置死信队列的exchange和queue,然后进行绑定
channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);
channel.queueDeclare("dlx.queue", true, false, false, null);
channel.queueBind("dlx.queue", "dlx.exchange", "#");
绑定:
agruments.put("x-dead-letter-exchange", "dlx.exchange");
//这个agruments属性,要设置到声明队列上
channel.queueDeclare(queueName, true, false, false, agruments);
channel.queueBind(queueName, exchangeName, routingKey);
死信队列, 可以处理异常情况下, 消息不能被正确处理或者超时被置于死信的情况, 可以分析异常情况进行改善, 也可以利用该队列实现延迟
三. 优先级队列:
优先级队列,设置消息优先级,进行插队处理, 优先级高的消息邮箱被消费处理
设置方法:设置对垒x-max-priority参数实现,(设置最大优先级, 消息优先级还需要在消息中设置)
设置发送消息优先级:
AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
builder.priority(5);
AMQP.BasicProperties properties = builder.build();
channel.basicPublish("exchange_priority","rk_priority",properties,("messages-"+i).getBytes());
如果在消息没有被堆积的情况下,消息能够被马上消费,优先级也没有什么用处了