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

概述

如果RabbitMQ服務器上有成千上萬條未處理的消息,如果我們這時我們運行消費端,一瞬間就會有巨量的消息推送過來,這個時候接收者因爲流量的劇增,超過了自己系統本身所能處理的最大峯值,如果沒有對消息做限流措施,接收服務器可能就會內存溢出,造成服務器不可用。

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;

代碼演示

  • 生產端
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條消息未被消費,一條消息等待簽收確認。只有當前消息簽收後,才消費剩餘的消息
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章