特点:
一个生产者对应几个消费者。模型如图:
1、 轮询分发 Round robin
1.1、生产者
package com.june.rabbitmq.workqueue;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Send {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
//获取连接
Connection connection = ConnectionUtil.getConnection();
//建立通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i=0;i<50;i++){
String msg = "send message june " + i + " hello!";
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
System.out.println("send message : " + msg);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
1.2、 消费者1
package com.june.rabbitmq.workqueue;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Recevice1 {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "utf-8");
System.out.println("[1] recevice message : " + message);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("[1] done!");
}
}
};
//监听队列 注册一个监听事件
channel.basicConsume(QUEUE_NAME, true, consumer);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
1.3、 消费者2
package com.june.rabbitmq.workqueue;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Recevice2 {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "utf-8");
System.out.println("[2] recevice message : " + message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("[2] done!");
}
}
};
//监听队列 注册一个监听事件
channel.basicConsume(QUEUE_NAME, true, consumer);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
1.4、现象:
消费者1和消费者2接收消息数量是一样的,消费者1接收的是奇数,消费者2接收的都是偶数。
这种叫轮询分发(Round-robin),均匀的给各个消费者分发消息,并不会忙或闲的都接收到一样多的消息。
注:需要先注册两个或以上消费者,不然如果先注册发送至再注册消费者的话,那会只给一个消费者发送。
2、 公平分发Fair dispatch
设置单个消费者同时处理的消息数量,在收到回发确认消息前,不再给消费者发送消息。这样就达到了谁处理快,谁就拿得多的目的,basicAck自动应答需要改成手动的。
注:这种的可以小注册发送端,因为不会一股脑的就给消费者全发过去。
2.1、生产者
package com.june.rabbitmq.workfair;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Send {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
//获取连接
Connection connection = ConnectionUtil.getConnection();
//建立通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
/**设置一次只处理一个消息,每个消费者在回发确认消息之前,队列不会发送第二个消息给同一个消费者
* 限制一个消费者同时消费的信息数量,限制为1条
* */
channel.basicQos(1);
for (int i=0;i<50;i++){
String msg = "send message june " + i + " hello!";
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
System.out.println("send message : " + msg);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
2.2、消费者1
package com.june.rabbitmq.workfair;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Recevice1 {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//设置同时只消费一条
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "utf-8");
System.out.println("[1] recevice message : " + message);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("[1] done!");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
//自动应答改为false
boolean autoAck = false;
//监听队列 注册一个监听事件
channel.basicConsume(QUEUE_NAME, autoAck, consumer);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
2.3、消费者2
package com.june.rabbitmq.workfair;
import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Recevice2 {
private static final String QUEUE_NAME = "june_work_queue";
public static void main(String[] args) {
try {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "utf-8");
System.out.println("[2] recevice message : " + message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("[2] done!");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
boolean autoAck = false;
//监听队列 注册一个监听事件
channel.basicConsume(QUEUE_NAME, autoAck, consumer);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}