• 过期时间 TTL
    • #设置消息的 TTL">#设置消息的 TTL
      • #在队列上设置">#在队列上设置
      • #在消息设置">#在消息设置
    • #设置队列的 TTL">#设置队列的 TTL

    过期时间 TTL

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

    #设置消息的 TTL

    • 通过队列设置:队列中的消息都有相同的过期时间
    • 对消息本身设置:每条消息的 TTL 可以不同

    如果两种一起设置,则以最小的 TTL 生效。
    消息在队列中生存时间一旦超过 TTL,就会变成「死信(Dead Message)」,消费者将无法收到该消息。(具体细节后续章节讲解)

    #在队列上设置

    定义队列时,通过参数 x-message-ttl 设置,单位是 毫秒

    1. final HashMap<String, Object> arguments = new HashMap<>();
    2. arguments.put("x-message-ttl", 6000);
    3. channel.queueDeclare(QUEUE_NAME, true, false, false, arguments);
    4. Copied!

    1
    2
    3

    TTL 值得几种情况:

    • 值为 0 :表示,除非此时可以直接将消息投递到消费者,否则该消息被立即丢弃
    • 大于 0:将在该时间内过期,

      #在消息设置

      通过 BasicProperties 来设置 expiration 属性:
    1. final AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties().builder();
    2. builder.deliveryMode(2); // 持久化消息
    3. builder.expiration("60000"); //设置消息的 ttl
    4. channel.basicPublish(EXCHANGE_NAME,
    5. "",
    6. true,
    7. builder.build(),
    8. "mandatory test".getBytes()
    9. );
    10. Copied!

    1
    2
    3
    4
    5
    6
    7
    8
    9

    此种方式当超过 TTL 时,并不会立即从队列中抹去,而是在投递消费者时判定的。而在队列上一旦过期,则立即从队列中抹去。
    这是因为内部实现的原因导致的:

    • 队列中已过期的消息肯定在队列头部,只要定期从队头开始扫描是否有过期的消息即可
    • 在消息中设置的过期,需要扫描整个队列。

    其实这个地方,笔者并不能明白书上锁讲的,为什么要扫描整个队列?队列过期为什么就会在头部?

    #设置队列的 TTL

    定义队列时间,通过参数 x-expires 参数,单位为毫秒

    1. final HashMap<String, Object> arguments = new HashMap<>();
    2. // 该参数必须大于 0,要么就不设置
    3. arguments.put("x-expires", 6000);
    4. channel.queueDeclare(QUEUE_NAME, true, false, false, arguments);
    5. channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);
    6. Copied!

    1
    2
    3
    4
    5

    队列的 TTL 其实就是在声明:当队列空闲多久时,被自动删除。
    空闲多久指的是:队列上没有任何消费者、也没有被重新声明、并且在过期时间内也未调用过 Basic.Get 命令
    适合使用的场景:可以应用在类似 RPC 方式的回复队列,在 RPC 中,许多队列会被创建出来,但是未被使用。(这里笔者也不知道什么是 RPC 回复队列)