RabbitMQ系列教程(九)RabbitMQ消费端限流

本文详细介绍了RabbitMQ的消费端限流机制,包括限流的重要性、原生API的代码实现,以及如何在SpringBoot项目中进行消费端限流。通过限流可以避免因大量未处理消息导致的内存溢出,确保系统的稳定运行。

1. 概述

如果RabbitMQ服务器上有成千上万条未处理的消息,如果我们这时我们运行消费端,一瞬间就会有巨量的消息推送过来,这个时候接收者因为流量的剧增,超过了自己系统本身所能处理的最大峰值,如果没有对消息做限流措施,接收服务器可能就会内存溢出,造成服务器不可用。

2. RabbitMQ限流机制

RabbitMQ提供了QOS限流功能,在非自动确认消息的前提下,如果有一定数目的未被确认前,不消费新的消息。

在消费端开启限流机制

  1. channel.basicConsume(...)方法的autoAck参数改为false
  2. 设置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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warybee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值