1. 概述
如果RabbitMQ服务器上有成千上万条未处理的消息,如果我们这时我们运行消费端,一瞬间就会有巨量的消息推送过来,这个时候接收者因为流量的剧增,超过了自己系统本身所能处理的最大峰值,如果没有对消息做限流措施,接收服务器可能就会内存溢出,造成服务器不可用。
2. RabbitMQ限流机制
RabbitMQ提供了QOS限流功能,在非自动确认消息的前提下,如果有一定数目的未被确认前,不消费新的消息。
在消费端开启限流机制
- 把
channel.basicConsume(...)方法的autoAck参数改为false - 设置Qos
channel.basicQos(0,1,false);
/**
* @param prefetchSize 消息的大小,设置为0不做任何限制
* @param prefetchCount 每次消费消息数
* @param global 为true channel级别的限流,false 消费端限流
*/
void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException;
3. 原生API代码演示
- 生产端
public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//设置虚拟主机
connectionFactory.setVirtualHost("/");
//创建一个链接
Connection connection = connectionFactory.newConnection();
//创建channel
Channel channel = connection.createChannel();
String exchangeName="test_qos_exchange";
String routeKey="qos.test";
String msg="RabbitMQ QOS message QOS test!";
for (int i=0;i<=4;i++){
channel.basicPublish(exchangeName,routeKey,null,msg.getBytes());
}
}
- 消费端
public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//设置虚拟主机
connectionFactory.setVirtualHost("/");
//创建链接
Connection connection = connectionFactory.newConnection();
//创建channel
Channel channel = connection.createChannel();
String exchangeName="test_qos_exchange";
String exchangeType="topic";
//声明Exchange
channel.exchangeDeclare(exchangeName,exchangeType,true,false,false,null);
String queueName="test_qos_queue";
//声明队列
channel.queueDeclare(queueName,true,false,false,null);
String routeKey="qos.#";
//绑定队列和交换机
channel.queueBind(queueName,exchangeName,routeKey);
//设置限流
channel.basicQos(0,1,false);
/**
* 把autoAck设置为false,限流才生效
*/
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("接收到消息::"+new String(body));
//不批量签收
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
如果想看限流效果可先把消费端的这行代码channel.basicAck(envelope.getDeliveryTag(),false);先注释。
在RabbitMQ控制台可以看到,有4条消息未被消费,一条消息等待签收确认。只有当前消息签收后,才消费剩余的消息

4.Spring boot项目中消费端限流
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "queue-springboot-test",
durable="true"),
exchange = @Exchange(value = "springboot_exchange_test",
durable="true",
type= "topic",
ignoreDeclarationExceptions = "true"),
key = "springboot.#"
))
@RabbitHandler
public void onMessage(Message message, Channel channel) throws Exception {
//消费端限流
channel.basicQos(0,1, false);
MessageHeaders messageHeaders=message.getHeaders();
System.err.println("--------------------------------------");
System.err.println("消费端接收到的消息: " + message.getPayload());
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
//手工ACK
channel.basicAck(deliveryTag, false);
}
具体可参考如下文章:
Spring AMQP API详解
Spring Boot整合RabbitMQ
RabbitMQ系列文章目录
1、RabbitMQ Windows/CentOS7平台安装手册
2、RabbitMQ中一些重要概念
3、RabbitMQ Exchange类型之Direct Exchange
4、RabbitMQ Exchange类型之Topic Exchange
5、RabbitMQ Exchange类型之fanout Exchange
6、RabbitMQ Exchange类型之headers Exchang
7、Confirm消息确认机制
8、RabbitMQ中ReturnListener的使用
9、RabbitMQ消费端限流
10、ACK确认机制与消息补偿
11、RabbitMQ队列/消息的生存时间(Time-To-Live)
12、RabbitMQ死信队列(Dead Letter Exchanges)
13、Spring AMQP API详解
14、Spring Boot整合RabbitMQ
本文详细介绍了RabbitMQ的消费端限流机制,包括限流的重要性、原生API的代码实现,以及如何在SpringBoot项目中进行消费端限流。通过限流可以避免因大量未处理消息导致的内存溢出,确保系统的稳定运行。
RabbitMQ消费端限流&spm=1001.2101.3001.5002&articleId=103164335&d=1&t=3&u=0c7bbe25b521471cb8669bb95d74e9c0)
5662

被折叠的 条评论
为什么被折叠?



