RabbitMQJava系列2-工作队列

 

工作队列分为两种,一种是轮询分发(Round-robin dispatching),另外一种是公平分发(Fair dispather)

轮询分发:MQ将消费逐一发给消费者,而不管消费者是否已经消费完成

 公平分发:MQ每次只发送1个未应答的消息给消费者,等待消费者应答后再次发送消息

代码实现

工厂工具类见Java系列1-简单队列

一、轮询分发:

消息生产者

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消息生产者:轮询分发(round-ribon)
*
* @author zy
*
*/
public class Send {
private static final String QUEUE_NAME = "test_round_ribon_queue";

public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
Channel channel = connection.createChannel();
// 创建队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 20; i++) {
String msg = "hello "+i;
// 发送
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
Thread.sleep(10L*i);
}
channel.close();
connection.close();
}
}

消息消费者1

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消费者1消费消息
*
* @author zy
*
*/
public class Receive {

private static final String QUEUE_NAME = "test_round_ribon_queue";

public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
Channel channel = connection.createChannel();
// 队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);

//基于事件
Consumer 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] receive msg:" + message);
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("[1] done");
}
}
};

// 监听队列
channel.basicConsume(QUEUE_NAME, true, consumer);
}

消息消费者2

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消费者2消费消息
*
* @author zy
*
*/
public class Receive2 {

private static final String QUEUE_NAME = "test_round_ribon_queue";

public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
Channel channel = connection.createChannel();
// 队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);

//基于事件
Consumer 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] receive msg:" + message);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("[2] done");
}
}
};

// 监听队列
channel.basicConsume(QUEUE_NAME, true, consumer);
}

}

 

二、公平分发

生产者:

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消息生产者:公平分发(fair-dispatch)
*
* @author zy
*
*/
public class Send {

private static final String QUEUE_NAME = "test_fair_queue";

public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
Channel channel = connection.createChannel();
// 创建队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 20; i++) {
String msg = "hello " + i;
// 发送
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
Thread.sleep(10L * i);
}
channel.close();
connection.close();
}
}

消费者1

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消费者1消费消息
*
* @author zy
*
*/
public class Receive {

private static final String QUEUE_NAME = "test_fair_queue";

public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
final Channel channel = connection.createChannel();
// 队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//一次处理一个
int prefetchCount = 1;
channel.basicQos(prefetchCount);
//基于事件
Consumer 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] receive msg:" + message);
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
//手动应答
channel.basicAck(envelope.getDeliveryTag(), false);
System.out.println("[1] done");
}
}
};

boolean autoAck = false;
// 监听队列
channel.basicConsume(QUEUE_NAME, autoAck, consumer);
}

}

消费者2:

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.zy.rabbitmq.util.ConnectionUtil;

/**
* 消费者2消费消息
*
* @author zy
*
*/
public class Receive2 {

private static final String QUEUE_NAME = "test_fair_queue";

public static void main(String[] args) throws IOException, TimeoutException {
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 从连接中获取一个通道
final Channel channel = connection.createChannel();
// 队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//一次处理一个
int prefetchCount = 1;
channel.basicQos(prefetchCount);
//基于事件
Consumer 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] receive msg:" + message);
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
//手动应答
channel.basicAck(envelope.getDeliveryTag(), false);
System.out.println("[2] done");
}
}
};

boolean autoAck = false;
// 监听队列
channel.basicConsume(QUEUE_NAME, autoAck, consumer);
}

 

代码总结:与轮询分发相比,公平分发需要在消费者端设置以下三项:

(1) 一次处理一个未应答的消息

//一次处理一个
int prefetchCount = 1;
channel.basicQos(prefetchCount);

(2)关闭自动应答

boolean autoAck = false;
// 监听队列
channel.basicConsume(QUEUE_NAME, autoAck, consumer);

(3)手动应答

channel.basicAck(envelope.getDeliveryTag(), false);

参考网站:http://www.rabbitmq.com/tutorials/tutorial-two-java.html

 

posted @ 2018-07-26 09:42  BingoTiger  阅读(136)  评论(0)    收藏  举报