更新时间:2023-05-06 GMT+08:00

死信和TTL

死信和TTL(Time To Live)是RabbitMQ中需要慎用的2个特性,它们可能会对性能产生负面影响。

死信

死信是RabbitMQ中的一种消息机制,在消费消息时,如果队列里的消息满足以下任意一种情况,那么该消息将成为“死信”。

  • “requeue”被设置为“false”,消费者使用“basic.reject”或“basic.nack”否定应答(NACK)消息。
  • 消息在队列的存活时间超过设置的TTL时间。
  • 队列的消息数量已经超过最大队列长度。

死信消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,该消息将会被存储到死信队列中,如果没有配置,该消息将会被丢弃。

更多关于死信的说明,请参考Dead Letter Exchanges

使用队列参数配置死信交换机和路由

为队列配置死信交换机,并在申明队列时指定“x-dead-letter-exchange”和“x-dead-letter-routing-key”参数。队列根据“x-dead-letter-exchange”将死信消息发送到死信交换机中,并根据“x-dead-letter-routing-key”为死信消息设置死信路由Key。

以下示例演示在Java客户端配置死信交换机和路由

channel.exchangeDeclare("some.exchange.name", "direct");

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "some.exchange.name");
args.put("x-dead-letter-routing-key", "some-routing-key");
channel.queueDeclare("myqueue", false, false, false, args);

TTL

TTL即过期时间。RabbitMQ支持设置消息和队列的TTL,消息的TTL可以通过以下两种方法设置:

  • 通过队列属性设置:队列中所有消息的具有相同的过期时间。
  • 对消息本身单独设置:每条消息可以设置不同的TTL。

如果两种方法同时使用,以较小的TTL为准。

消息在队列中的生存时间超过了TTL后,消息会被丢弃,如果队列设置了死信交换机,丢弃的消息会被转发到死信交换机,由死信交换机将其路由到死信队列。

更多关于TTL的说明,请参考TTL

设置队列TTL

通过channel.queueDeclare方法中的“x-expires”参数控制队列被自动删除前处于未使用状态的时间。未使用是指队列中没有任何消费者,也没有被重新声明,并且在过期时间段内也未调用过Basic.Get命令。“x-expires”参数的值必须为非零整数,单位为毫秒。

以下示例演示在Java客户端设置队列TTL。

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

设置消息TTL

通过队列属性设置消息TTL:在channel.queueDeclare方法中加入“x-message-ttl”参数,此参数的值必须为非零整数,单位为毫秒。

以下示例演示在Java客户端通过队列属性设置消息TTL。

Map<String,Object> arg = new HashMap<String, Object>();
arg.put("x-message-ttl",6000);
channel.queueDeclare("normalQueue",true,false,false,arg); 

对消息本身单独设置TTL:在channel.basicPublish方法中加入“expiration”参数,此参数的值必须为非零整数,单位为毫秒。

以下示例演示在Java客户端对消息本身单独设置TTL。

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