引言

它是一种通过广播方式发送消息的路由器,所有和exchange建立的绑定关系的队列都会接收到消息

不处理路由键,只需要简单的将队列绑定到交换机上

fanout交换机转发消息是最快的,它不需要做路由键的匹配

1.模型

2.Exchange

Exchange在我们的工作模型中首次出现,因此需要详细介绍下。

Exchange:接收消息,并根据路由键转发消息到所绑定的队列。

Exchange分为4种类型:

Direct:完全根据key进行投递的,例如,绑定时设置了routing key为”abc”,那么客户端提交的消息,只有设置了key为”abc”的才会投递到队列。
Topic:对key进行模式匹配后进行投递,符号”#”匹配一个或多个词,符号”*”匹配正好一个词。例如”abc.#”匹配”abc.def.ghi”,”abc.*”只匹配”abc.def”。
Fanout:不需要key,它采取广播模式,一个消息进来时,投递到与该交换机绑定的所有队列。

交换机属性:

Durable:是否需要持久化,true为持久化

AutoDelete:当最后一个绑定到Exchange上的队列删除后,自动删除该Exchange

Internal:当前Exchange是否用于Rabbitmq的内部使用,默认是false(用Erlang语言进行内部功能扩展会使用到)

Arguments:扩展参数,用于扩展AMQP协议自定义使用

今天我们的实例采用fanout类型的exchange。

3.Queue-消息队列

消息队列,实际存储消息数据
Durability:是否持久化,Durable:true,Transient:false
AutoDelete:true代表当最后一个监听被移除之后,该Queue会自动被删除。

通过RabbitMQ 接口可以自己去生成临时队列,队列名字也由RabbitMQ自动生成。通过

可以声明一个非持久的、通道独占的、自动删除的队列,getQueue()方法可以获取随机队列名字。这个名字用来在队列和exchange之间建立binding关系的时候使用:

4.Message-消息

服务器和应用程序之间传递的数据
本质上就是一段数据,由Properties和Payload(Body)组成
常用属性:
delivery mode:投递模式,2表示持久化投递
headers:自定义属性
content_type:消息内容格式
content_encoding:编码格式
priority:优先级

reply_to:一般用于RPC过程,消息处理返回结果队列;
  correlation_id:用于关联RPC的请求与应答;

expiration:过期时间
message_id:消息id

5.创建生产者

package com.dwz.rabbitmq.exchange.fanout;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_fanout_exchange"; String msg = "hello rabbitmq fanout message successs!--";
for(int i = 0; i < 50; i++) {
channel.basicPublish(exchangeName, "", null, (msg + i).getBytes());
} channel.close();
connection.close();
}
}

6.创建消费者1

package com.dwz.rabbitmq.exchange.fanout;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); //交换机名称
String exchangeName = "test_fanout_exchange";
//交换机类型
String exchangeType = "fanout";
String queueName = "test_fanout_queue_1";
//路由键
String routingKey = "";
//交换机声明
channel.exchangeDeclare(exchangeName, exchangeType, true, false, null);
/*
* durable:持久化,服务器重启,数据仍然存在
* exclusive:独占一个channel,用于顺序消费,类似于加了一把锁
* autoDelete:如果一个队列脱离了exchange会自动删除
*/
//队列声明
channel.queueDeclare(queueName, false, false, false, null);
//队列绑定交换机
channel.queueBind(queueName, exchangeName, routingKey); //定义消费者
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body, "utf-8");
System.out.println("rec1--message:" + msg);
}
};
//设置消费者
channel.basicConsume(queueName, true, consumer);
}
}

7.创建消费者2

package com.dwz.rabbitmq.exchange.fanout;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.dwz.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel(); String exchangeName = "test_fanout_exchange";
String exchangeType = "fanout";
String queueName = "test_fanout_queue_2";
String routingKey = "";
channel.exchangeDeclare(exchangeName, exchangeType, true, false, null);
/*
* durable:持久化,服务器重启,数据仍然存在
* exclusive:独占一个channel,用于顺序消费,类似于加了一把锁
* autoDelete:如果一个队列脱离了exchange会自动删除
*/
channel.queueDeclare(queueName, false, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey); DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body, "utf-8");
System.out.println("rec2--message:" + msg);
}
};
channel.basicConsume(queueName, true, consumer);
}
}

8.运行代码

先启动两个消费者,再启动生产者,运行结果:

两个消费者都拿到exchange(交换机)的全部信息

注:由于exchange只是做一个消息转发,本身是不具备存储数据的能力,如果先启动生产者,信息是到达不了队列的,队列有存储数据的功能

参考文章:

RabbitMQ学习笔记

fanout(Publish/Subscribe)发布/订阅的更多相关文章

  1. php redis pub/sub(Publish/Subscribe,发布/订阅的信息系统)之基本使用

    一.场景介绍 最近的一个项目需要用到发布/订阅的信息系统,以做到最新实时消息的通知.经查找后发现了redis pub/sub(发布/订阅的信息系统)可以满足我的开发需求,而且学习成本和使用成本也比较低 ...

  2. 译: 3. RabbitMQ Spring AMQP 之 Publish/Subscribe 发布和订阅

    在第一篇教程中,我们展示了如何使用start.spring.io来利用Spring Initializr创建一个具有RabbitMQ starter dependency的项目来创建spring-am ...

  3. 理解 Redis(9) - Publish Subscribe 消息订阅

    在窗口1开通一个名为 redis 的通道: 127.0.0.1:6379> SUBSCRIBE redis Reading messages... (press Ctrl-C to quit) ...

  4. Jedis实现发布订阅功能

    Redis为我们提供了publish/subscribe(发布/订阅)功能.我们可以对某个channel(频道)进行subscribe(订阅),当有人在这个channel上publish(发布)消息时 ...

  5. C/S模式,发布/订阅模式和PUSH/PULL模式(上)

    CS模式(客户端/服务器模式) 最场景的信息传递模式,也称为Request/Response模式,或者调用模式.http/https协议即此模式.因为最常用所以大家一般都比较熟悉,这里不重点讲了,大家 ...

  6. Redis学习篇(十一)之发布订阅

    PUBLISH/SUBSCRIBE 发布订阅的原理 包含两个角色,一个是发布者, 一个是订阅者 订阅者可以订阅一个或者多个频道(channel) 发布者可以向指定的频道发布信息 通过SUBSCRIBE ...

  7. RabbitMQ入门-发布订阅模式

    兔子的Publish/Subscribe是这样的: 有个生产者P,X代表交换机,交换机绑定队列,消费者从队列中取得消息.每次有消息,先发到交换机中,然后由交换机负责发送到它已知的队列中. 生产者代码: ...

  8. Linux - redis发布|订阅

    目录 Linux - redis发布|订阅 发布|订阅 基本命令 发布和订阅实例 正则方式订阅一个或者多个符合模式的频道 Linux - redis发布|订阅 发布: publish 订阅: subs ...

  9. go使用go-redis操作redis 连接类型,pipline, 发布订阅

    内容: 一 . 客户端Client(普通模式,主从模式,哨兵模式)二. conn连接(连接, pipline, 发布订阅等)三. 示例程序(连接, pipline, 发布订阅等)客户端Client 普 ...

  10. Redis进阶篇:发布订阅模式原理与运用

    "65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?" "那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆 ...

随机推荐

  1. ASP.NET使用AJAX应注意IIS有没有.ashx扩展

    项目添加引用AJAX.DLL了:今天将本地做好的一个web程序放到服务器上,居然报告错误了.web程序使用了ajax来往返数据. 检查生成的html语句,有这么两句代码<script type= ...

  2. C#委托的定义 以及使用方式详解,更简单的理解委托。

    委托的声明及定义: 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得 ...

  3. python对比线程,进程,携程,异步,哪个快

    目录概念介绍测试环境开始测试测试[单进程单线程]测试[多进程 并行]测试[多线程 并发]测试[协程 + 异步]结果对比绘图展示概念介绍首先简单介绍几个概念: 进程和线程进程就是一个程序在一个数据集上的 ...

  4. java面试1

    1.面向对象的特征·有·哪些方面 1)抽象 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽 ...

  5. conda查找安装包的版本以及安装特定版本的包

    如下图 想要安装特定版本的torchvision,然后conda search torchvision,能够列出conda云上所有的安装包 然后,安装包的时候,conda install 包名=版本就 ...

  6. python 列表字典按照字典中某个valu属性进行排序

    对用户名进行排序 1. 直接上代码 base_dn_list = [ {', 'tenant': 'HAD', 'role': {'roleID': 'project', 'roleName': '项 ...

  7. 在不同的Linux发行版上安装TFTP Server

    http://www.davidsudjiman.info/2006/03/27/installing-and-setting-tftpd-in-ubuntu/ http://www.cybercit ...

  8. weakref:对象的弱引用

    介绍 weakref支持对象的弱引用,正常的引用会增加对象的引用计数,并避免它被垃圾回收.但结果并不是总和期望的那样,比如有时候可能会出现一个循环引用,或者有时候需要内存时可能要删除对象的缓存.而弱引 ...

  9. C语言的宏macro的使用

    C's Macro Introduction 1.The Connect Macros: ## 这是一个预处理连接符,这个操作符主要用来将两个符号连接成为一个完整的宏符号.通过下面的代码,可以看到其具 ...

  10. apache2.4.9编译安装

    源码编译安装 由于centos7的版本可以支撑所以在centos6上编译安装 centos6 准备 gzip wget 安装 yum install gzip wget -y apr . apr-ut ...