在第一次声明交换器时被指定,用来提供一种预先存在的交换器,如果主交换器无法路由消息,那么消息将被路由到这个新的备用交换器。
如果发布消息时同时设置了mandatory会发生什么?如果主交换器无法路由消息,RabbitMQ并不会通知发布者,因为,向备用交换器发送消息,表示消息已经被路由了。注意,新的备用交换器就是普通的交换器,没有任何特殊的地方。
使用备用交换器,向往常一样,声明Queue和备用交换器,把Queue绑定到备用交换器上。然后在声明主交换器时,通过交换器的参数,alternate-exchange,,将备用交换器设置给主交换器。
建议备用交换器设置为faout类型,Queue绑定时的路由键设置为“#”
代码实现:
主消费者
public class MainConsumer {
public static void main(String[] argv)
throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
// 打开连接和创建频道,与发送端一样
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
// 声明一个队列
String queueName = "focuserror";
channel.queueDeclare(queueName,
false,false,
false,null);
String severity="error";//只关注error级别的日志,然后记录到文件中去。
channel.queueBind(queueName,
BackupExProducer.EXCHANGE_NAME, severity);
System.out.println(" [*] Waiting for messages......");
// 创建队列消费者
final Consumer consumerB = 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( "Received ["
+ envelope.getRoutingKey() + "] "+message);
}
};
channel.basicConsume(queueName, true, consumerB);
}
}
备用消费者
public class BackupExConsumer {
public static void main(String[] argv)
throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
// 打开连接和创建频道,与发送端一样
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.exchangeDeclare(BackupExProducer.BAK_EXCHANGE_NAME,
BuiltinExchangeType.FANOUT,
true, false, null);
// 声明一个队列
String queueName = "fetchother";
channel.queueDeclare(queueName,
false,false,
false,null);
channel.queueBind(queueName,
BackupExProducer.BAK_EXCHANGE_NAME, "#");
System.out.println(" [*] Waiting for messages......");
// 创建队列消费者
final Consumer consumerB = 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( "Received ["
+ envelope.getRoutingKey() + "] "+message);
}
};
channel.basicConsume(queueName, true, consumerB);
}
}
生产者
public class BackupExProducer {
public final static String EXCHANGE_NAME = "main-exchange";
public final static String BAK_EXCHANGE_NAME = "ae";
public static void main(String[] args)
throws IOException, TimeoutException {
/**
* 创建连接连接到RabbitMQ
*/
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
// 创建一个连接
Connection connection = factory.newConnection();
// 创建一个信道
Channel channel = connection.createChannel();
// 声明备用交换器
Map<String,Object> argsMap = new HashMap<String,Object>();
argsMap.put("alternate-exchange",BAK_EXCHANGE_NAME);
//主交换器
channel.exchangeDeclare(EXCHANGE_NAME,"direct",
false,false,argsMap);
//备用交换器
channel.exchangeDeclare(BAK_EXCHANGE_NAME,BuiltinExchangeType.FANOUT,
true,false,null);
//所有日志严重性级别
String[] severities={"error","info","warning"};
for(int i=0;i<3;i++){
//每一次发送一条不同严重性的日志
String severity = severities[i%3];
// 发送的消息
String message = "Hello World_"+(i+1);
//参数1:exchange name
//参数2:routing key
channel.basicPublish(EXCHANGE_NAME, severity,
null, message.getBytes());
System.out.println(" [x] Sent '" + severity +"':'"
+ message + "'");
}
// 关闭频道和连接
channel.close();
connection.close();
}
}