问题
:::tips 当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息达到上限,之后发送的消息就会成为死信,可能会被丢弃,这就是消息堆积问题
解决消息堆积有两种思路:
- 增加更多消费者,提高消费速度,也就是使用work queue工作队列模型
- 扩大队列容积,提高堆积上限
要提升队列容积,把消息保存在内存中显然是不行的
- 队列过长的话会占用系统较多内存,RabbitMQ为了释放内存,会将队列消息转储到硬盘,称为page out,如果队列很长,page out操作会消耗较长时间,且page out过程中队列不能处理消息,因此会出现间歇性的暂停状态、并发时出现波浪性的忽高忽低现象
- 队列过长同时会加长RabbitMQ重启时间,因为启动时候需要重建索引
- 队列过长还会导致集群之间节点同步消息时间变长
从RabbitMQ的3.6.0版本开始,就增加了Lazy Queues的概念,也就是惰性队列,惰性队列的特征如下:
- 接收到消息后直接存入磁盘而非内存
- 消费者要消费消息时才会从磁盘中读取并加载到内存
- 支持数百万条的消息存储
- 基于磁盘存储,消息时效性会降低
- 性能受限于磁盘的IO
-
声明惰性队列
基于@Bean方式
:::tips 在消息消费者的配置类中声明惰性队列 ::: ```java @Configuration public class XxxConfig{
//声明惰性队列 @Bean public Queue lazyQueue(){
return QueueBuilder
.durable("lazy.queue") //设置队列名称并指定为持久化队列
.lazy() //设置惰性队列
.build();
}
}
<a name="rB0BN"></a>
### 基于注解方式
:::tips
在消息消费者的RabbitMqListener类中新增消费者,使用@RabbitListener注解的属性来声明惰性队列
:::
```java
//将这个类注册到Spring容器中
@Component
public class RabbitMqListener {
//声明惰性队列,同时监听队列中的消息
@RabbitListener(queuesToDeclare = @Queue(
name = "lazy.queue",
arguments = @Argument(name = "x-queue-mode", value = "lazy") //声明惰性队列
))
public void listen(String msg){
System.out.println("接收到消息:" + msg);
}
}