【RabbitMQ】高级特性(消费端限流、过期时间、死信队列、延迟队列)

消费端限流

消费端限流是为了防止消息积压后,消费端一次拉取过多的消息而挂掉。

我们限制一个数字,其含义是:当所有的消息都被手动确认之后,消费者可以拉取的最大消息数。

在这里插入图片描述


核心配置:

(1)在<rabbit:listener-container>中设置 prefetch="30"

(2)消费端的确认模式一定是手动确认,即 acknowledge="manual"

<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" prefetch="30">
	<rabbit:listener ref="xxxListener" queue-names="xxx_queue"></rabbit:listener>
</rabbit:listener-container>

 
 
 

过期时间

当一个消息达到TTL(存活时间,也叫过期时间)后还没有被消费,那么它会被自动清除。

我们可以单独对某个消息设置过期时间,也可以对整个队列设置统一的过期时间。


❶ 消息单独过期时间

生产者发送消息时,给单个消息设置 expiration 参数,字符串类型,单位ms。

rabbitTemplate.convertAndSend("exchange_ttl", "routing_key", "我是一个TTL消息~", new MessagePostProcessor() {
	public Message postProcessMessage(Message message) throws AmqpException {
		// 设置message的参数
		message.getMessageProperties().setExpiration("5000");
		// 返回message
		return message;
	}
});

❷ 队列整体过期时间

配置队列时,给队列设置 x-message-ttl 参数,整型,单位ms。

<rabbit:queue name="queue_ttl" id="queue_ttl">
	<!-- 设置队列的参数 -->
	<rabbit:queue-arguments>
		<entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"></entry>
	</rabbit:queue-arguments>
</rabbit:queue>

当我们给一个消息设置超时时间后,是不是过了这个时间,消息队列就 立即 将该消息清除了呢?
不是。如果想要实现超时立即删除,那么需要一直轮询检查每个消息,这开销过大。因此,消息队列对超时消息的清除,是一种 惰性删除 —— 当某个消息位于队列头部,即将被消费时,才会对其进行一次超时检查,如果超时,则清除。

 
 
 

死信队列

在这里插入图片描述

死信队列和死信交换机是一个概念,有两种叫法是因为有的MQ产品中没有交换机的概念。


看图不难理解:

  1. 当一个队列中的消息成为死信后,不会被清除,而是被送到另一个交换机
  2. 这第二个交换机就叫做死信交换机,它和普通交换机其实没什么两样

一个消息如何成为死信呢(重点)?

  1. 时间过期。当消息达到过期时间仍未被消费时,便成为死信
  2. 长度限制。一个队列满了,之后来的消息都成为死信
  3. 消息拒收。消费者拒绝确认某个消息,且该消息不重回队列,则其成为死信

下面,我们看着图,手写一个死信队列模型:

(1) 声明正常队列和正常交换机(queue_normal, exchange_normal)

(2) 声明死信队列和死信交换机(queue_dlx, exchange_dlx)

(3) 绑定正常队列和死信交换机(x-dead-letter-exchange, x-dead-letter-routing-key)

<!--
        1.声明正常队列和正常交换机(queue_normal, exchange_normal)
        2.声明死信队列和死信交换机(queue_dlx, exchange_dlx)
        3.绑定正常队列和死信交换机(x-dead-letter-exchange, x-dead-letter-routing-key)
-->

<!-- 正常队列/正常交换机 -->
<rabbit:queue name="queue_normal" id="queue_normal">
	<rabbit:queue-arguments>
		<entry key="x-dead-letter-exchange" value="exchange_dlx"/>
		<entry key="x-dead-letter-routing-key" value="routing_key"/>
		<entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"/>
		<entry key="x-max-length" value="10" value-type="java.lang.Integer"/>
	</rabbit:queue-arguments>
</rabbit:queue>
<rabbit:direct-exchange name="exchange_normal" id="exchange_normal">
	<rabbit:bindings>
		<rabbit:binding key="routing_key" queue="queue_normal"></rabbit:binding>
	</rabbit:bindings>
</rabbit:direct-exchange>

<!-- 死信队列/死信交换机 -->
<rabbit:queue name="queue_dlx" id="queue_dlx"></rabbit:queue>
<rabbit:direct-exchange name="exchange_dlx" id="exchange_dlx">
	<rabbit:bindings>
		<rabbit:binding key="routing_key" queue="queue_dlx"></rabbit:binding>
	</rabbit:bindings>
</rabbit:direct-exchange>

分别测试3中成为死信的情况:

生产者端 ------------------------------------------------------------------------------------

// case1:过期时间
rabbitTemplate.convertAndSend("exchange_normal", "routing_key", "我会成为死信消息吗?");

// case2:长度限制
for (int i = 0; i < 20; i++) {
	rabbitTemplate.convertAndSend("exchange_normal", "routing_key", "我会成为死信消息吗?");
}


消费者端 ------------------------------------------------------------------------------------
// case3:拒接接收
// 注意设置不重回队列(第三个参数)
channel.basicNack(message.getMessageProperties().getDeliveryTag(), true, false);

 
 
 

延迟队列

消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。

延迟队列的使用场景其实非常多:

(1)订单在30min之内未支付则自动取消

(2)用户注册成功后,如果三天内没有登录则进行短信提醒


很可惜,在RabbitMQ中并未提供具有延迟队列功能的黑箱。但是,我们可以通过 TTL + DLX (过期时间 + 死信队列)来实现延迟队列的效果。

在这里插入图片描述

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

🐰 Rabbit~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值