Ezreal 书架 Ezreal 书架
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
  • RabbitMQ简介

  • RabbitMQ 入门

  • 客户端开发向导

  • RabbitMQ 进阶

    • 消息何去何从
    • 过期时间 (TTL)
      • 设置消息的 TTL
      • 设置队列的 TTL
    • 死信队列
    • 延迟队列
    • 优先级队列
    • RPC 实现
    • 持久化
    • 生产者确认
    • 消费端要点介绍
    • 消息传输保障
    • 小结
  • RabbitMQ 管理

  • RabbitMQ实战指南
  • RabbitMQ 进阶
ezreal_rao
2023-04-04
目录

过期时间 (TTL)

TTL, Time to Live 的简称,即过期时间。 RabbitMQ 可以对消息和队列设置 TTL。

# 设置消息的 TTL

目前有两种方法可以设置消息的 TTL。第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。第二种方法是对消息本身进行单独设置,每条消息的 TTL 可以不同。如果两种方法一起使用,则消息的 TTL 以两者之间较小的那个数值为准。消息在队列中的生存时间一旦超过设置的 TTL 值时,就会变成 "死信" (Dead Message) ,消费者将无法再收到该消息 (这点不是绝对的,可以参考 4.3 节)。

通过队列属性设置消息 TTL 的方法是在 channel.queueDeclare 方法中加入 x-message-ttl 参数实现的,这个参数的单位是毫秒。

示例代码如代码清单 4-3 所示。

代码清单 4-3

Map<String , Object> argss = new HashMap<String , Object>();

argss.put("x-message-ttl", 6000); 
channel.queueDeclare(queueName, durable, exclusive, autoDelete, argss);
1
2
3
4

同时也可以通过 Policy 的方式来设置 TTL,示例如下 :

rabbitmqctl set_policy TTL ".*" '{" message-ttl" :60000}' --apply-to queues
1

还可以通过调用 HTTPAPI 接口设置 :

$ curl -i -u root:root -H " content-type:application/json" -X PUT -d'{"auto_delete":false,"durable":true,"arguments":{"x-message-ttl":60000}}' http://localhost:15672/api/queues/{vhost}/{queuename}
1

如果不设置 TTL. 则表示此消息不会过期;如果将 TTL 设置为 0,则表示除非此时可以直接将消息投递到消费者,否则该消息会被立即丢弃,这个特性可以部分替代 RabbitMQ 3.0 版本之前的 immediate 参数,之所以部分代替,是因为 immediate 参数在投递失败时会用 Basic.Return 将消息返回 (这个功能可以用死信队列来实现,详细参考 4.3 节)。

针对每条消息设置 TTL 的方法是在 channel.basicPublish 方法中加入 expiration 的属性参数,单位为毫秒。

关键代码如代码清单 4-4 所示。

代码清单 4-4

AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();

builder.deliveryMode(2); // 持久化消息 
builder.expiration("60000");// 设置 TTL=60000ms

AMQP.BasicProperties properties = builder.build(); 
channel.basicPublish(exchangeName, routingKey, mandatory, properties, "ttlTestMessage".getBytes());
1
2
3
4
5
6
7

也可以使用如代码清单 4-5 所示的方式:

代码清单 4-5

AMQP.BasicProperties properties = new AMQP.BasicProperties() ;
Properties.setDeliveryMode(2);
properties.setExpiration("60000");
channel.basicPublish (exchangeName, routingKey, mandatory, properties, "ttlTestMessage".getBytes());
1
2
3
4

还可以通过 HTTPAPI 接口设置 :

$ curl -i - u root:root -H "content-type:application/json" -X POST -d '{"properties":{"expiration":"60000"},"routing key":"routingkey","payload":"my body","payload_encoding":" string"}' http://localhost:15672/api/exchanges/{vhost}/{exchangename}/publish
1

对于第一种设置队列 TTL 属性的方法,一旦消息过期,就会从队列中抹去,而在第二种方法中,即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期是在即将投递到消费者之前判定的。

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

# 设置队列的 TTL

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

::: waring
设置消息的 ttl 是 x-message-ttl 参数控制的,而队列的过期时间是 x-expires 参数控制的,都是在队列声明时设置的参数。
:::

设置队列里的 TTL 可以应用于类似 RPC 方式的回复队列,在 RPC 中,许多队列会被创建出来,但是却是未被使用的。

RabbitMQ 会确保在过期时间到达后将队列删除,但是不保障删除的动作有多及时 。在 RabbitMQ 重启后, 持久化的队列的过期时间会被重新计算。

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

代码清单 4-6 演示了创建一个过期时间为 30 分钟的队列:

代码清单 4-6

Map<String , Object> args = new HashMap<String , Object>();
args.put( "x-expires", 1800000);
channel.queueDeclare("myqueue", false, false, false, args) ;
1
2
3
#mq#rabbitmq#amq
上次更新: 5/9/2023, 10:58:32 AM
消息何去何从
死信队列

← 消息何去何从 死信队列→

最近更新
01
为什么我的MySQL会抖一下
07-15
02
HTTP 性能优化面面观
07-12
03
WebSocket:沙盒里的 TCP
07-12
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Ezreal Rao | CC BY-NC-SA 4.0
豫ICP备2023001810号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式