这是我参与更文挑战的第5天,活动详情查看: 更文挑战
work消息模型
官方翻译:工人之间分配任务(竞争者模型)
上一篇我们是一个生产者一个消费者,这一篇我们创建work,在多个消费者之间分配任务。
工作队列,又名任务队列,避免执行资源密集型任务时,必须等到执行结束,我们把消息发到队列,消费者获取消息并消费,多个消费者的时候并行执行,但是一个消息只能被消费一次。
p: 生产者 负责生产消息
c1:消费者1
c2:消费者2
c1与c2相比处理消息更快一点
生产者
public class Producer_HelloWorld {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//2.设置参数
connectionFactory.setHost("192.168.145.3");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/zhaojin");
connectionFactory.setUsername("zhaojin");
connectionFactory.setPassword("zhaojin");
//3.创建连接
Connection connection = connectionFactory.newConnection();
//4.创建 channel
Channel channel = connection.createChannel();
//5.创建queue
channel.queueDeclare("hello_world",true,false,false,null);
//6.发送
for (int i = 0; i < 50; i++) {
String bady ="hello RabbitMQ 第"+i+"次";
channel.basicPublish("","hello_world",null,bady.getBytes());
System.out.println("生产者发送消息"+bady);
}
//7.释放资源
channel.close();
connection.close();
}
}
消费者1
public class c1 {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//2.设置参数
connectionFactory.setHost("192.168.145.3");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/zhaojin");
connectionFactory.setUsername("zhaojin");
connectionFactory.setPassword("zhaojin");
//3.创建连接
Connection connection = connectionFactory.newConnection();
//4.创建 channel
Channel channel = connection.createChannel();
channel.queueDeclare("hello_world",true,false,false,null);
//6.接受消息
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("c1消费消息: "+new String(body));
//手动ack
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("hello_world",false,consumer);
}
}
消费者2
public class c2 {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//2.设置参数
connectionFactory.setHost("192.168.145.3");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/zhaojin");
connectionFactory.setUsername("zhaojin");
connectionFactory.setPassword("zhaojin");
//3.创建连接
Connection connection = connectionFactory.newConnection();
//4.创建 channel
Channel channel = connection.createChannel();
channel.queueDeclare("hello_world",true,false,false,null);
//6.接受消息
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("c2消费消息 :"+new String(body));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//手动ack
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("hello_world",false,consumer);
}
}
设置了消费者2暂停1m来表示消费速度,然后同时打开c1c2,再打开生产者发送50条消息。看控制台运行情况。
虽然都消费了25条消息,实现了任务的分发,但是消费者1处理任务快,处理结束他一直处于空闲状态,但是两个人处理的消息是一样多的,这样不好,要的是处理快的人多处理消息。怎么实现呢,我们可以设置告诉MQ一次性不要给一个消费者发送多余一条的消息,不要向正再工作的人发消息,知道ack确认了再发,相反把消息发给干活快的人。
//设置同时只处理一条
channel.basicQos(1);
再次运行,可以看到能者处理了大部分分的工作。