RabbitMQ(二)AMQP协议mandatory和immediate标志位区别中我们提到,在RabbitMQ3.0以后的版本里,去掉了immediate参数支持,要实现类似的确认功能要使用TTL和DLX。

 

TTL,Time-To-Live Extensions(过期时间)

RabbitMQ 允许你对 message 和 queue 设置 TTL 值。

Per-Queue Message TTL

通过在 queue.declare 中设置 x-message-ttl 参数,可以控制被 publish 到 queue 中的 message 被丢弃前能够存活的时间。当某个 message 在 queue 留存的时间超过了配置的 TTL 值时,我们说该 message “已死”。值得注意的是,当一个 message 被路由到多个 queue 中时,其可以在不同的时间“死掉”,或者可能有的不会出现“死掉”情况。在某个 queue 中的某个 message 的“死亡”不会对相同 message 在其他 queue 中的生存状况。

服务器会保证“死掉”的 message 将不会被包括在任何的 basic.get-ok 或 basic.deliver 方法中。更进一步,服务器将努力在 TTL 到期或到期后的短时间内处理掉该 message 。

参数 x-message-ttl 的值 必须是非负 32 位整数 (0 <= n <= 2^32-1) ,以毫秒为单位表示 TTL 的值。这样,值 1000 表示存在于 queue 中的当前 message 将最多只存活 1 秒钟,除非其被投递到 consumer 上。实参可以是以下 AMQP 类型:short-short-int 、short-int 、long-int 或者 long-long-int 。

下面的 Java 实例代码创建了一个 queue ,且 message 在该 queue 的存活时间最大为 60 秒: :

  1. <span style="font-size:14px;">Map<String, Object> args = new HashMap<String, Object>();
  2. args.put("x-message-ttl", 60000);
  3. channel.queueDeclare("myqueue", false, false, false, args);</span>

另外也可以用rabbitctl的set_policy来设置:

  1. <span style="font-size:14px;">rabbitmqctl set_policy TTL ".*" '{"message-ttl":60000}' --apply-to queues</span>

还可以通过HTTP接口调用如下:

  1. <span style="font-size:14px;">$ curl -i -u guest:guest -H "content-type:application/json"  -XPUT
  2. -d'{"auto_delete":false,"durable":true,"arguments":{"x-message-ttl": 60000}}'
  3. http://localhost:15672/api/queues/{vhost}/{queuename}</span>

当 message 被 requeue 的时候,其原始过期时间将被保留(例如由于设置了 requeue 参数的 AMQP 方法的使用,或者由于 channel 的关闭)。

设置 x-message-ttl 为 0 将使得,在 message 在到达 queue 之后但尚未被立即投递到 consumer 的情况下,判定为过期。这种方式相当于 RabbitMQ server 在3.0.0以后不支持 basic.publish 中 immediate 标识情况下的等价实现。与 immediate 标帜方式不同的是,将不会有 basic.returns 命令的调用,但是在设置了 dead letter exchange 的情况下,这些 message 将被处理为 dead-lettered(详见下面的DLX) 。

Per-Message TTL

在RabbitMQ 3.0.0以后的版本中,TTL 设置可以具体到每一条 message 本身,只要在通过 basic.publish 命令发送 message 时设置 expiration 字段。

expiration 字段以微秒为单位表示 TTL 值。且与 x-message-ttl 具有相同的约束条件。因为 expiration 字段必须为字符串类型,broker 将只会接受以字符串形式表达的数字。

当同时指定了 queue 和 message 的 TTL 值,则两者中较小的那个才会起作用。

下面的 Java 示例 publish 了最多能在 queue 中存活 60 秒的 message :

  1. <span style="font-size:14px;">byte[] messageBodyBytes = "Hello, world!".getBytes();
  2. AMQP.BasicProperties properties = new AMQP.BasicProperties();
  3. properties.setExpiration("60000");
  4. channel.basicPublish("myexchange", "routingkey", properties, messageBodyBytes);</span>

还可以通过HTTP接口调用如下:

  1. <span style="font-size:14px;">$ curl -i -u guest:guest -H "content-type:application/json"  -XPOST
  2. -d'{"properties":{"expiration":"60000"},"routing_key":"routingkey","payload":"my
  3. body","payload_encoding":"string"}'
  4. http://localhost:15672/api/exchanges/{vhost}/{exchangename}/publish</span>

虽然 consumer 从来看不到过期的 message ,但是在过期 message 到达 queue 的头部时确实会被真正的丢弃(或者 dead-lettered )。当对每一个 queue 设置了 TTL 值时不会产生任何问题,因为过期的 message 总是会出现在 queue 的头部。当对每一条 message 设置了 TTL 时,过期的 message 可能会排队于未过期 message 的后面,直到这些消息被 consume 到或者过期了。在这种情况下,这些过期的 message 使用的资源将不会被释放,且会在 queue 统计信息中被计算进去(例如,queue 中存在的 message 的数量)。

对于第一种设置队列TTL属性的方法,一旦消息过期,就会从队列中抹去,而第二种方法里,即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期时在即将投递到消费者之前判定的,为什么两者得处理方法不一致?因为第一种方法里,队列中已过期的消息肯定在队列头部,RabbitMQ只要定期从队头开始扫描是否有过期消息即可,而第二种方法里,每条消息的过期时间不同,如果要删除所有过期消息,势必要扫描整个队列,所以不如等到此消息即将被消费时再判定是否过期,如果过期,再进行删除。

Queue TTL

queue.declare 命令中的 x-expires 参数控制 queue 被自动删除前可以处于未使用状态的时间。未使用的意思是 queue 上没有任何 consumer ,queue 没有被重新声明,并且在过期时间段内未调用过 basic.get 命令。该方式可用于,例如,RPC-style 的回复 queue ,其中许多 queue 会被创建出来,但是却从未被使用。

服务器会确保在过期时间到达后 queue 被删除,但是不保证删除的动作有多么的及时。在服务器重启后,持久化的 queue 的超时时间将重新计算。

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

下面的 Java 示例创建了一个 queue ,其会在 30 分钟不使用的情况下判定为超时。

    1. Map<String, Object> args = new HashMap<String, Object>();
    2. args.put("x-expires", 1800000);
    3. channel.queueDeclare("myqueue", false, false, false, args);

RabbitMQ(三)RabbitMQ消息过期时间(TTL)的更多相关文章

  1. 【RabbitMQ 实战指南】一 过期时间TTL

    RabbitMQ 可以对消息和队列设置过期时间(TTL) 1.设置消息的TTL 目前有两种方式可以设置消息的TTL 第一种方式是通过队列属性设置,队列中所有消息都有相同的过期时间 第二种方式是对消息本 ...

  2. ActiveMQ队列消息过期时间设置和自动清除解决方案

    版本 apache-activemq-5.15.3 1.消息过期设置 参数详情 1)message过期则客户端不能接收 2)ttlCeiling:表示过期时间上限(程序写的过期时间不能超过此时间,超过 ...

  3. rabbitmq队列中消息过期配置

    最近公司某个行情推送的rabbitmq服务器由于客户端异常导致rabbitmq队列中消息快速堆积,还曾导致过内存积压导致rabbitmq客户端被block的情况.考虑到行情信息从业务上来说可以丢失部分 ...

  4. RabbitMQ 设置队列的过期时间

    设置队列的过期时间非常简单,在声明队列时,设置x-expires参数即可.当队列的生存周期超时后,RabbitMQ server会自动将该队列删除. 代码如下: channel.QueueDeclar ...

  5. rabbitmq设置队列消息存活时间

    public static final int ALIVETIME = 600000; public static final String QUEUE = "hnyz_gs_queue&q ...

  6. RabitMq过期时间TTL

    第一种:给消息设置过期时间 启动一个插件 @Bean public DirectExchange DirectExchange() { return new DirectExchange(" ...

  7. RabbitMQ 设置消息的TTL(过期时间)

    我们在RabbitMQ中发布消息时,在代码中有两种方法设置某个队列的消息过期时间: 1.针对队列来说,可以使用x-message-ttl参数设置当前队列中所有消息的过期时间,即当前队列中所有的消息过期 ...

  8. RabbitMQ之TTL(Time-To-Live 过期时间)

    本文转载自RabbitMQ之TTL(Time-To-Live 过期时间) 概述 RabbitMQ可以对消息和队列设置TTL. 目前有两种方法可以设置.第一种方法是通过队列属性设置,队列中所有消息都有相 ...

  9. rabbitMq 学习笔记(二) 备份交换器,过期时间,死信队列,死信队列

    备份交换器 备份交换器,英文名称为 Altemate Exchange,简称庙,或者更直白地称之为"备胎交换器". 生产者在发送消息的时候如果不设置 mandatory 参数, 那 ...

随机推荐

  1. 【三种负载均衡器的优缺点】LVS Nginx HAProxy

    搭建负载均衡高可用环境相对简单,主要是要理解其中原理.此文描述了三种负载均衡器的优缺点,以便在实际的生产应用中,按需求取舍. 目前,在线上环境中应用较多的负载均衡器硬件有F5 BIG-IP,软件有LV ...

  2. 使用MyBatista----上传图像

    使用MyBatis上传图像,使用的是Oracle的数据库表,有一个TEACHER表,有7列,有1列是存储图片的,类型用BLOB,最大容量是4G,以二进制的形式写入数据库表. 建立这个表的对应实体类Te ...

  3. Google JavaScript代码风格指南

    Google JavaScript代码风格指南 修正版本 2.28 Aaron Whyte Bob Jervis Dan Pupius Eric Arvidsson Fritz Schneider R ...

  4. 亲历dataguard的一些经验问答题

    问题1:是否log_archive_dest_n=service中进程使用lgwr时(如log_archive_dest_2='service=DBSTD LGWR SYNC'),备库就一定要建立st ...

  5. SPOJ LCS2 多个串的最长公共子串

    这里串最多有10个,找所有串的最长公共子串 这里后缀自动机做,以第一个串建立后缀自动机,后面的串一个个去匹配,每次得到当前串在可到达状态上所能得到的最长后缀长度 拿所有串匹配后得到的结果进行计算 #i ...

  6. SQL Server 创建唯一约束sql语句

    SQL Server 创建唯一约束sql语句   语句示例:   在创建表是时同时创建, 创建id,name,sex三个字段的唯一索引 create table t1( id int primary ...

  7. AlertDialog自定义

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  8. 2018 百度之星 初赛 第六题 HDU6349

    三原色图  Accepts: 281  Submissions: 1261  Time Limit: 1500/1000 MS (Java/Others)  Memory Limit: 262144/ ...

  9. MySQL中的数据类型的长度范围和显示宽度(转)

    长度范围是随数据类型就已经是固定的值,而显示宽度与长度范围无关. 以下是每个整数类型的存储和范围(来自MySQL手册) 类型 字节 最小值 最大值 (带符号的/无符号的) (带符号的/无符号的) TI ...

  10. 【面试被虐】如何只用2GB内存从20亿,40亿,80亿个整数中找到出现次数最多的数?

    这几天小秋去面试了,不过最近小秋学习了不少和位算法相关文章,例如 [面试现场]如何判断一个数是否在40亿个整数中? [算法技巧]位运算装逼指南 对于算法题还是有点信心的,,,,于是,发现了如下对话. ...