-
10条消息,2个普通消费者,1个拒绝消费者,requeue=true,消费前
-
消费后,经过轮询消费者A消费了1、4、7、10,消费者B消费了2、5、8,拒绝消费者消费了3、6、9
-
3、6、9被拒绝之后,返回队列中重新投递
-
3进入消费者B,6进入拒绝消费者,9进入消费者A;然后6再次被拒绝,进入队列再次重新投递,进入消费者B
上代码
1.创建生产者RejectProducer,生产10条消息
package com.rabbit.fisher.rejectmsg;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
*消息消费的拒绝
*/
public class RejectProducer
{
public final static String EXCHANGE_NAME="direct_logs";
public static void main( String[] args ) throws IOException, TimeoutException {
//创建链接、连接到MQ
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接工厂的连接地址(默认端口5672)
connectionFactory.setHost("192.168.42.111");
//设置虚拟主机
connectionFactory.setVirtualHost("fisher");
//设置用户名
connectionFactory.setUsername("fisher");
//设置密码
connectionFactory.setPassword("123456");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//在信道中设置交换器(这里选择直接交换器direct)
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//在消费者中申明队列
//申明路由键及消息体
for (int i = 0; i < 10; i++) {
String route = "error";
String msg = "Hello World" + (i+1);
//发布消息(设置交换器、路由键、参数、消息内容)
channel.basicPublish(EXCHANGE_NAME, route, null, msg.getBytes());
System.out.println("Send:" + route + ";" + msg);
}
//关闭信道
channel.close();
//关闭连接
connection.close();
}
}
2.创建消费者AConsumerA,
package com.rabbit.fisher.rejectmsg;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
*direct类型交换器的消费者
*/
public class ConsumerA
{
public static void main( String[] args ) throws IOException, TimeoutException {
//创建链接、连接到MQ
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接工厂的连接地址(默认端口5672)
connectionFactory.setHost("192.168.42.111");
//设置虚拟主机
connectionFactory.setVirtualHost("fisher");
//设置用户名
connectionFactory.setUsername("fisher");
//设置密码
connectionFactory.setPassword("123456");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建信道
final Channel channel = connection.createChannel();
//在信道中设置交换器
channel.exchangeDeclare(RejectProducer.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//申明队列
String queueName = "rejectqueue";
channel.queueDeclare(queueName, false, false, false, null);
//绑定:将队列与交换器通过路由键绑定
String routeKey = "error";
channel.queueBind(queueName, RejectProducer.EXCHANGE_NAME, routeKey);
System.out.println("waiting for message ......");
//申明一个消费者
final 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("Receive[" + envelope.getRoutingKey() + "]" + message);
channel.basicAck(envelope.getDeliveryTag(), false);
}
};
channel.basicConsume(queueName, false, consumer);
}
}
3.创建消费者BConsumerB
package com.rabbit.fisher.rejectmsg;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
*direct类型交换器的消费者
*/
public class ConsumerB
{
public static void main( String[] args ) throws IOException, TimeoutException {
//创建链接、连接到MQ
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接工厂的连接地址(默认端口5672)
connectionFactory.setHost("192.168.42.111");
//设置虚拟主机
connectionFactory.setVirtualHost("fisher");
//设置用户名
connectionFactory.setUsername("fisher");
//设置密码
connectionFactory.setPassword("123456");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建信道
final Channel channel = connection.createChannel();
//在信道中设置交换器
channel.exchangeDeclare(RejectProducer.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//申明队列
String queueName = "rejectqueue";
channel.queueDeclare(queueName, false, false, false, null);
//绑定:将队列与交换器通过路由键绑定
String routeKey = "error";
channel.queueBind(queueName, RejectProducer.EXCHANGE_NAME, routeKey);
System.out.println("waiting for message ......");
//申明一个消费者
final 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("Receive[" + envelope.getRoutingKey() + "]" + message);
channel.basicAck(envelope.getDeliveryTag(), false);
}
};
channel.basicConsume(queueName, false, consumer);
}
}
4.创建拒绝消费者RejectConsumer,使用Reject方式channel.basicReject(envelope.getDeliveryTag(), true);或使用Nack方式channel.basicNack(envelope.getDeliveryTag(), true, true);效果一样
package com.rabbit.fisher.rejectmsg;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;
/**
*拒绝消息的消费者
*/
public class RejectConsumer
{
public static void main( String[] args ) throws IOException, TimeoutException {
//创建链接、连接到MQ
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接工厂的连接地址(默认端口5672)
connectionFactory.setHost("192.168.42.111");
//设置虚拟主机
connectionFactory.setVirtualHost("fisher");
//设置用户名
connectionFactory.setUsername("fisher");
//设置密码
connectionFactory.setPassword("123456");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建信道
final Channel channel = connection.createChannel();
//在信道中设置交换器
channel.exchangeDeclare(RejectProducer.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//申明队列
String queueName = "rejectqueue";
channel.queueDeclare(queueName, false, false, false, null);
//绑定:将队列与交换器通过路由键绑定
String routeKey = "error";
channel.queueBind(queueName, RejectProducer.EXCHANGE_NAME, routeKey);
System.out.println("waiting for message ......");
//申明一个消费者
final Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
try {
String message = new String(body, "UTF-8");
System.out.println("Receive[" + envelope.getRoutingKey() + "]" + message);
throw new RuntimeException("异常处理" + message);
} catch (RuntimeException e) {
e.printStackTrace();
//Reject方式拒绝(第二个参数决定是否重新投递,设置为true表示重新投递,设置false则消息丢失)
channel.basicReject(envelope.getDeliveryTag(), true);
//Nack方式拒绝(第二个参数决定是否批量,第三个参数决定是否重新投递)
// channel.basicNack(envelope.getDeliveryTag(), true, true);
}
}
};
channel.basicConsume(queueName, false, consumer);
}
}