RabbitMQ公平队列实现
1.什么是公平队列?
消费集群的情况下,第一个消费者,消费一个消息需要5秒钟,另一个消费者消费一条数据需要1秒钟,这个时候均摊消费就会造成第一个消费者压力大,而第二个消费者很快就消费完啦,那么第二个消费者没事可做,第一个消费者消费速度缓慢,这个时候我们就需要另一个消费者帮助第一个消费者进行消费!
白话文比喻:一个3年的java工程师和一个实习生java工程师,3年的java工程师做东西很快,而实习生做东西很慢,那么这个时候就要发挥能者多劳的行为,3年的工程师多做一点,实习生少做一点!
这就叫公平消费队列
2.接下来是代码环节
生产者生产50条信息:
package com.producer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.utils.MQConnectionUtils;
//简单队列生产者
public class Producer {
//队列名称
private static final String QUEUE_NAME ="zrf_644";
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建一个新的连接
Connection connection = MQConnectionUtils.newConnection();
//2.创建通道
Channel channel = connection.createChannel();
//3.创建一个队列 参数1:队列名称 参数2:是否持久化 参数3:是否唯一 参数4:是否自动删除
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for(int i=0;i<50;i++) {
//4.创建消息
String msg ="zrf_644444msg:"+i;
//5.生产者发送消息
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
System.out.println("生产者发送消息成功:"+msg);
}
//6.关闭通道和连接
channel.close();
connection.close();
}
}
启动消费者01:
package com.consumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
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;
import com.utils.MQConnectionUtils;
public class Consumer {
//队列名称
private static final String QUEUE_NAME ="zrf_644";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("消费者01");
//1.创建一个新的连接
Connection connection = MQConnectionUtils.newConnection();
//2.创建通道
final Channel channel = connection.createChannel();
//3.创建一个队列 参数1:队列名称 参数2:是否持久化 参数3:是否唯一 参数4:是否自动删除
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
/*
* 4.限制发送给同一个消费者不得超过一条消息
* 每个消费者发送确认消息之前,消息队列不发送下一条消息至消费者,一次只处理一条消息
*/
channel.basicQos(1);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
//监听获取消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
byte[] body) throws IOException {
String msg = new String(body,"UTF-8");
System.out.println("消费者获取生产者消息:"+msg);
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}finally {
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
//设置应该模式 设置为true 表示默认自动应答 设置为false,则为手动应答
channel.basicConsume(QUEUE_NAME, false,defaultConsumer);
}
}
启动消费者02:
package com.consumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
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;
import com.utils.MQConnectionUtils;
public class Consumer {
//队列名称
private static final String QUEUE_NAME ="zrf_644";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("消费者02");
//1.创建一个新的连接
Connection connection = MQConnectionUtils.newConnection();
//2.创建通道
final Channel channel = connection.createChannel();
//3.创建一个队列 参数1:队列名称 参数2:是否持久化 参数3:是否唯一 参数4:是否自动删除
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
//监听获取消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
byte[] body) throws IOException {
String msg = new String(body,"UTF-8");
System.out.println("消费者获取生产者消息:"+msg);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}finally {
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
//设置应该模式 设置为true 表示默认自动应答 设置为false,则为手动应答
channel.basicConsume(QUEUE_NAME, false,defaultConsumer);
}
}
然后自己测试一下就懂了