一、Fanout模型的定义与创建过程
fanout既可以称为广播模型,又可以称为发布/订阅模型
他的创建过程为
1.生产者通道绑定交换机
channel.exchangeDeclare("fanout_ex","fanout");
其中两个参数分别表示要绑定的交换机(不存在就创建)和交换机的类型
2. 生产者向交换机发送消息
在fanout模式下,生产的消息都是发送给交换机而不是队列。
channel.basicPublish("fanout_ex","",null, "发送给交换机的信息<>".getBytes());
3.消费者通道绑定交换机
与生产者绑定交换机一样,声明交换机名称和类型
channel.exchangeDeclare("fanout_ex","fanout");
4.当前通道生成临时的队列
为了减轻RabbitMq队列的压力,fanout模式通常使用临时队列,用完即删除。
//生成临时队列获得该队列的名字
String queueName = channel.queueDeclare().getQueue();
5.通过通道连接交换机-临时队列-消费者
//绑定交换机和临时队列,不需要使用路由
channel.queueBind(queueName,"fanout_ex","");
6. 消费者和生产者启动的顺序
消费者必须限于生产者启动,否则先启动生产者的话,exchange接到消息后发现没有队列对它感兴趣,就任性的把消息给丢掉了
二、代码实现
1. 生产者线程
public class ProviderTh extends Thread{
@Override
public void run() {
Connection connection = null;
Channel channel = null;
try {
connection = RabbitMqUtil.getConnection();
channel = connection.createChannel();
/**
* 绑定交换机和通道
* 参数1: String 交换机名称
* 参数2: String 交换机类型
*/
channel.exchangeDeclare("fanout_ex","fanout");
//发送消息,指明交换机而不指明队列, 这条消息就是发送给交换机的
for (int i = 0; i < 10; i++) {
channel.basicPublish("fanout_ex","",null, "发送给交换机的信息<>".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
RabbitMqUtil.closeChannelAndConnection(channel,connection);
}
}
}
2.消费者线程
public class CustomerTh extends Thread {
private String name;
public CustomerTh(String name) {
this.name = name;
}
@Override
public void run() {
super.run();
Connection connection = null;
Channel channel = null;
try {
connection = RabbitMqUtil.getConnection();
channel = connection.createChannel();
//通道绑定交换机
channel.exchangeDeclare("fanout_ex","fanout");
//生成临时队列
String queueName = channel.queueDeclare().getQueue();
//绑定交换机和临时队列
channel.queueBind(queueName,"fanout_ex","");
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(name + "=> 消费了:" + new String(body));
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
启动方法
注意,消费者在这里先于生产者启动
public static void main(String[] args) throws InterruptedException {
//先启动消费者, 再启动生产者
Thread c1 = new CustomerTh("c1");
c1.start();
Thread c2 = new CustomerTh("c2");
c2.start();
Thread.sleep(1000);
ProviderTh providerTh = new ProviderTh();
providerTh.start();
}