跳到主要内容
版本:4.1

Time-to-Live 和过期

本文档指南涵盖的主要主题包括

Time-To-Live 功能

使用 RabbitMQ,您可以为消息和队列设置 TTL(生存时间)参数或策略。顾名思义,TTL 指定消息和队列“存活”的时间段。

消息 TTL 确定消息可以在队列中保留多长时间。如果消息在队列中的保留时间超过队列的消息 TTL,则消息将过期并被丢弃。

“丢弃”意味着消息将不会传递给任何订阅的消费者,并且无法通过直接应用于队列的 basic.get 方法访问。消息 TTL 可以应用于单个队列、一组队列或逐条消息应用。

TTL 也可以在队列上设置,而不仅仅是队列内容。此功能可以与自动删除队列属性一起使用。在队列上设置 TTL(过期)通常仅对瞬态(非持久)经典队列有意义。流不支持过期。

队列仅在不使用时才会经过一段时间后过期(如果队列具有在线消费者,则队列正在使用)。

TTL 行为由 可选队列参数 控制,配置它的最佳方法是使用 策略

TTL 设置也可以通过 操作员策略 强制执行。

队列中每个队列的消息 TTL

可以通过使用 策略 设置 message-ttl 参数,或在队列声明时指定相同的参数,来为给定队列设置消息 TTL。

在队列中存在时间超过配置的 TTL 的消息被称为已过期。请注意,路由到多个队列的消息可能在每个队列中过期时间不同,或者根本不过期。一条消息在一个队列中的死亡不会影响同一消息在其他队列中的生命周期。

服务器保证过期消息不会使用 basic.deliver(传递给消费者)或在响应轮询消费者时发送(在 basic.get-ok 响应中)。

此外,服务器将尝试在消息基于 TTL 的过期时间或之后不久删除消息。

TTL 参数或策略的值必须是非负整数(等于或大于零),描述以毫秒为单位的 TTL 周期。

因此,值 1000 表示添加到队列的消息将在队列中保留 1 秒,或者直到它被传递给消费者。该参数可以是 AMQP 0-9-1 类型 short-short-intshort-intlong-intlong-long-int

使用策略为队列定义消息 TTL

要使用策略指定 TTL,请将键“message-ttl”添加到策略定义中

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

这会将 60 秒的 TTL 应用于所有队列。

在声明期间使用 x-arguments 为队列定义消息 TTL

Java 中的此示例创建一个队列,其中消息最多可以驻留 60 秒

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-message-ttl", 60000);
channel.queueDeclare("myqueue", false, false, false, args);

C# 中的相同示例

var args = new Dictionary<string, object>();
args.Add("x-message-ttl", 60000);
model.QueueDeclare("myqueue", false, false, false, args);

可以将消息 TTL 策略应用于已包含消息的队列,但这涉及 一些注意事项

如果消息被重新排队(例如,由于使用了具有重新排队参数的 AMQP 方法,或者由于通道关闭),则消息的原始过期时间将被保留。

将 TTL 设置为 0 会导致消息在到达队列时过期,除非它们可以立即传递给消费者。因此,这提供了 immediate 发布标志的替代方案,RabbitMQ 服务器不支持该标志。与该标志不同,不会发出 basic.return,如果设置了死信交换机,则消息将被死信。

发布者中每个消息的 TTL

可以通过在发布消息时设置 expiration 属性,在每个消息的基础上指定 TTL。

expiration 字段的值描述了以毫秒为单位的 TTL 周期。与 x-message-ttl 相同的约束适用。由于 expiration 字段必须是字符串,因此 broker 将(仅)接受数字的字符串表示形式。

当同时指定每个队列和每个消息的 TTL 时,将选择两者之间的较低值。

此示例使用 RabbitMQ Java 客户端 发布一条消息,该消息最多可以在队列中驻留 60 秒

byte[] messageBodyBytes = "Hello, world!".getBytes();
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.expiration("60000")
.build();
channel.basicPublish("my-exchange", "routing-key", properties, messageBodyBytes);

C# 中的相同示例

byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!");

IBasicProperties props = model.CreateBasicProperties();
props.ContentType = "text/plain";
props.DeliveryMode = 2;
props.Expiration = "60000";

model.BasicPublish(exchangeName,
routingKey, props,
messageBodyBytes);

每个消息的 TTL 和死信队列

仲裁队列

仲裁队列在过期消息到达队列头部时对其进行死信处理。

经典队列

经典队列在以下几种情况下对过期消息进行死信处理

  • 当消息到达队列头部时
  • 当队列收到影响它的策略更改通知时

追溯应用于每个消息的 TTL(应用于现有队列)

追溯应用了每个消息 TTL 的队列(当它们已经有消息时)将在特定事件发生时丢弃消息。

只有当过期的消息到达队列头部时,它们才会被实际丢弃(标记为删除)。消费者不会收到过期的消息。请记住,在消息过期和消费者传递之间可能存在自然的竞争条件,例如,消息可能在写入套接字后但在到达消费者之前过期。

当设置每个消息的 TTL 时,过期的消息可能会在未过期的消息后面排队,直到后者被消费或过期。因此,此类过期消息使用的资源将不会被释放,并且它们将被计入队列统计信息(例如,队列中消息的数量)。

当追溯应用每个消息的 TTL 策略时,建议让消费者在线以确保消息更快地被丢弃。

鉴于现有队列上每个消息的 TTL 设置的这种行为,当需要删除消息以释放资源时,应使用队列 TTL(或队列清除或队列删除)来代替。

队列 TTL

TTL 也可以在队列上设置,而不仅仅是队列内容。此功能可以与 自动删除队列属性 一起使用。

在队列上设置 TTL(过期)通常仅对瞬态(非持久)经典队列有意义。流不支持过期。

队列仅在不使用时才会经过一段时间后过期(如果队列具有在线消费者,则队列正在使用)。

可以通过将 x-expires 参数设置为 queue.declare,或通过设置 expires 策略,为给定队列设置过期时间。这控制队列在自动删除之前可以未被使用多长时间。未使用意味着队列没有消费者,队列最近未被重新声明(重新声明会续订租约),并且 basic.get 在至少过期期间内未被调用。这可以用于例如 RPC 样式的回复队列,其中可以创建许多可能永远不会被耗尽的队列。

服务器保证队列在至少过期期间内未使用的情况下将被删除。对于队列在过期期间过后多久会被删除,不提供任何保证。

x-expires 参数或 expires 策略的值描述了以毫秒为单位的过期期间。它必须是正整数(与消息 TTL 不同,它不能为 0)。因此,值 1000 表示未使用的队列 1 秒将被删除。

使用策略为队列定义队列 TTL

以下策略使所有队列在上次使用后 30 分钟过期

rabbitmqctl
rabbitmqctl set_policy expiry ".*" '{"expires":1800000}' --apply-to queues
rabbitmqctl (Windows)
rabbitmqctl.bat set_policy expiry ".*" "{""expires"":1800000}" --apply-to queues

在声明期间使用 x-arguments 为队列定义队列 TTL

Java 中的此示例创建一个队列,该队列在未使用 30 分钟后过期。

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-expires", 1800000);
channel.queueDeclare("myqueue", false, false, false, args);
© . All rights reserved.