使用场景
首先,我们Rabbitmq服务器有上万条未处理的消息,我们随便打开一个消费者客户端,会出现如下情况: 巨量的消息瞬间全部推送过来,但是我们单个客户端无法同时处理这么多数据! Rabbitmq提供了一种qos(服务质量保证)功能,即在非自动确认消息的前提下,如果一定数目的消息 (通过基于consumer或者channel设置qos的值)未被确认前,不进行消费新的消息。
具体方法
void BasicQos(unit prefetchSize, ushort prefetchCount, boolean global); prefetchSize:单条消息的大小限制,通常设置为0,意思是不做限制 prefetchCount:消息的条数,一般设置为1条 global:消息针对的级别,true:channel级别,false:consumer级别,通常设置为false
注意:prefetchSize和global这两项,rabbitmq没有实现,暂且不做研究,prefetchCount在自动应答的情况下是不生效的,必须进行手动签收
创建生产者
package com.dwz.rabbitmq.qos; import java.io.IOException; import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; public class Producer { public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtils.getConnection(); Channel channel = connection.createChannel(); String exchangeName = "test_qos_exchange"; String routingkey = "qos.save"; String msg = "Hello rabbitmq qos message!"; for(int i = 0; i < 5; i++) { channel.basicPublish(exchangeName, routingkey, null, msg.getBytes()); }
channel.close();
connection.close();
} }
创建消费者
package com.dwz.rabbitmq.qos; import java.io.IOException; import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer { public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtils.getConnection(); Channel channel = connection.createChannel(); String exchangeName = "test_qos_exchange"; String routingkey = "qos.#"; String queueName = "test_qos_queue"; channel.exchangeDeclare(exchangeName, "topic", true, false, null); channel.queueDeclare(queueName, true, false, false, null); channel.queueBind(queueName, exchangeName, routingkey); //限流 channel.basicQos(0, 1, false); DefaultConsumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body); //手动签收(因为只传递一条数据过来,所以不用批量接收 multiple=false) channel.basicAck(envelope.getDeliveryTag(), false); } }; //限流方式,第一件事就是autoAck设置为false channel.basicConsume(queueName, false, consumer); } }
相关文章: