https://gitee.com/DanShenGuiZu/learnDemo/tree/master/rabbitMq-learn/rabbitMq-03
basicQos(int prefetchCount);
basicQos(int prefetchCount, boolean global);
basicQos(int prefetchSize, int prefetchCount, boolean global);
一个生产者生产了20条消息,有两个消费者:Consumer、Consumer2。并将这两个消费者的prefetchCount值 设置成5,Consumer 设置为 手动ACK,而 Consumer2 自动ACK
package com.example.rabbitmq03.business.test8;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Producer {
public static void main(String[] args) {
// 1. 获取连接
Connection connection = null;
try {
connection = RabbitMqUtil.getConnection("生产者");
} catch (Exception e) {
System.out.println("获取连接时,出现异常");
}
Channel channel = null;
try {
// 2. 通过连接获取通道 Channel
channel = connection.createChannel();
String queueName = "code_simple_queue1";
// 3. 通过通道创建声明队列
channel.queueDeclare(queueName, false, false, false, null);
// 4. 发送消息给队列 Queue
for (int i = 0; i < 20; i++) {
// 5. 准备消息内容
String message = "你好 " + i;
channel.basicPublish("", queueName, null, message.getBytes());
System.out.println("消息发送完成~~~发送的消息为:" + message);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
RabbitMqUtil.close(connection, channel);
} catch (Exception e) {
System.out.println("关闭时,出现异常");
}
}
}
}
package com.example.rabbitmq03.business.test8;
import java.io.IOException;
import com.rabbitmq.client.*;
public class Consumer {
public static void main(String[] args) throws Exception {
// 获取连接
Connection connection = RabbitMqUtil.getConnection("消费者");
final Channel channel = connection.createChannel();
String queueName = "code_simple_queue1";
// 定义消费者
com.rabbitmq.client.Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
byte[] body) throws IOException {
// 消息id,mq 在 channel 中用来标识消息的 id,可用于确认消息已接收
long deliveryTag = envelope.getDeliveryTag();
// body 消息体
String msg = new String(body, "utf-8");
System.out.println("收到消息:" + msg);
/**
* @param1:deliveryTag:用来标识消息的id
* @param2:multiple:是否批量。true:将一次性 ACK 所有小于 deliveryTag 的消息
*/
// 手动确认
channel.basicAck(deliveryTag, false);
}
};
// 限制未 ACK 的消息最大数
channel.basicQos(5, false);
// 监听队列 手动 ACK
channel.basicConsume(queueName, false, consumer);
System.out.println("开始接收消息~~~");
System.in.read();
// 关闭信道、连接
RabbitMqUtil.close(connection, channel);
}
}
Consumer2和Consumer唯一区别就是注释了 手动ACK代码
package com.example.rabbitmq03.business.test8;
import java.io.IOException;
import com.rabbitmq.client.*;
public class Consumer2 {
public static void main(String[] args) throws Exception {
// 获取连接
Connection connection = RabbitMqUtil.getConnection("消费者");
final Channel channel = connection.createChannel();
String queueName = "code_simple_queue1";
// 定义消费者
com.rabbitmq.client.Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
byte[] body) throws IOException {
// 消息id,mq 在 channel 中用来标识消息的 id,可用于确认消息已接收
long deliveryTag = envelope.getDeliveryTag();
// body 消息体
String msg = new String(body, "utf-8");
System.out.println("收到消息:" + msg);
/**
* @param1:deliveryTag:用来标识消息的id
* @param2:multiple:是否批量。true:将一次性 ACK 所有小于 deliveryTag 的消息
*/
// 手动确认
// channel.basicAck(deliveryTag, false);
// 它只消费消息,并未确认消息。因为我们这里没有设置手动确认
}
};
// 限制未 ACK 的消息最大数
channel.basicQos(5, false);
// 监听队列 手动 ACK
channel.basicConsume(queueName, false, consumer);
System.out.println("开始接收消息~~~");
System.in.read();
// 关闭信道、连接
RabbitMqUtil.close(connection, channel);
}
}
Consumer 消费了 15 条消息,因为它每消费一条就 ACK 一条,另外 5 条消息被另一个 Consumer2 给持有。
Consumer2 消费了 5 条消息,但它都没有确认,由于 channel.basicQos(5, false) 的缘故,它就没再消费消息了。所有MQ里面有5条没有确认的消息
高并发情况下,队列里面一瞬间就就积累了上万条数据,但是消费者无法同时处理这么多请求,这个时候当我们打开客户端,瞬间就有巨量的信息给推送过来、但是客户端是没有办法同时处理这么多数据的,结果就是消费者(客户端)挂掉了
channel.basicQos(int prefetchSize, int prefetchCount, boolean global);
# 对消息本身的大小不限制,但是同一时刻最大只能接受10条消息。
channel.basicQos(0, 10, false);