一、fanout(发布订阅模式)
为了说明发布/订阅模式,我们构建一个简单的日志系统。它有两个程序组成,第一个程序是发出日志消息,第二个程序是消费者。我们启动两个消费者,其中一个消费者接收到消息后把日志存储在磁盘,另一个消费者接收到消息后把消息打印在屏幕上,实际上第一个程序发出的日志消息将广播给所有消费者。
1、fanout,是将接收到的所有消息广播到它知道的所有队列中。系统中默认有些exchange类型
1、1实战
交换机会将消息广播给与他有binging关系的队列,以工不同的消费者使用。
Logs交换机和临时队列的绑定关系如下:
发布订阅模式,生产者通过交换机以广播的形式将消息发布出去,与交换机有binding关系的的队列接收到消息后,各个消费者消费其对应队列中的消息。
代码:
生产者:
package com.example.rabbitmq.five;
import com.example.rabbitmq.rabbitMqUtils.RabbitUtils;
import com.rabbitmq.client.Channel;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.TimeoutException;
// 发消息 交换机
public class EmitLogs {
// 交换机的名称
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitUtils.getChannel();
// 声明交换机,fanout表示发布订阅模式
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String message = scanner.next();
/*
* 发送一个消息
* 1、发送到哪个交换机
* 2、路由routing key是哪个,本次binding 可以使用空串
* 3、其他参数信息
* 4、发送消息的消息体
* */
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println("生产者发出消息:" + message);
}
}
}
消费者1
package com.example.rabbitmq.five;
import com.example.rabbitmq.rabbitMqUtils.RabbitUtils;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 交换机:发布订阅模式
* ReceiveLog01将接收到的消息打印在控制台
**/
public class ReceiveLog01 {
// 交换机的名称
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitUtils.getChannel();
// 声明一个交换机
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
// 声明一个临时队列
/**
* 生成一个临时队列,名称随机
* 当消费之断开与队列的链接时候,临时队列就会自动删除
*
* */
String queueName = channel.queueDeclare().getQueue();
/**
* 绑定交换机与队列
*
* */
channel.queueBind(queueName, EXCHANGE_NAME, "");// routingkey可以是空串
System.out.println("ReceiveLog01等待接收消息,把接收到的消息打印在控制台输出......");
// 接收消息
DeliverCallback deliverCallback = (consumeTag, message) -> {
System.out.println("ReceiveLog01控制台打印接收到的消息:" + new String(message.getBody()));
};
// 消费者取消消息时回调接口
CancelCallback cancelCallback = (consumerTag) -> {
System.out.println(consumerTag + "消息者取消消费回调逻辑");
};
channel.basicConsume(queueName, true, deliverCallback, cancelCallback);
}
}
消费者2
package com.example.rabbitmq.five;
import com.example.rabbitmq.rabbitMqUtils.RabbitUtils;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ReceiveLog02 {
// 交换机的名称
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitUtils.getChannel();
// 声明一个交换机
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
// 声明一个临时队列
/**
* 生成一个临时队列,名称随机
* 当消费之断开与队列的链接时候,临时队列就会自动删除
*
* */
String queueName = channel.queueDeclare().getQueue();
/**
* 绑定交换机与队列
*
* */
channel.queueBind(queueName, EXCHANGE_NAME, "");// routingkey可以是空串
System.out.println("ReceiveLog02等待接收消息,把接收到的消息打印在控制台输出......");
// 接收消息
DeliverCallback deliverCallback = (consumeTag, message) -> {
System.out.println("ReceiveLog02控制台打印接收到的消息:" + new String(message.getBody()));
};
// 消费者取消消息时回调接口
CancelCallback cancelCallback = (consumerTag) -> {
System.out.println(consumerTag + "消息者取消消费回调逻辑");
};
channel.basicConsume(queueName, true, deliverCallback, cancelCallback);
}
}
生产者发布消息,通过交换机广播出去,消费者01和02都接收到消息: