A. 用广播的方式实现发布订阅

参考资料:https://www.rabbitmq.com/tutorials/tutorial-three-java.html

Fanout 类型的 Exchange 以广播的方式向所有绑定到该 Exchange 的队列推送消息。

下面样例代码试图使用 fanout 将状态变更消息推送给所有接入系统:

gordon.study.rabbitmq.fanout.Fanout.java

public class Fanout {

    private static final String EXCHANGE_NAME = "StatusUpdateFanout";

    public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection(); final Channel senderChannel = connection.createChannel();
senderChannel.exchangeDeclare(EXCHANGE_NAME, "fanout");
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 10;) {
String message = "NO. " + ++i;
TimeUnit.MILLISECONDS.sleep(100);
senderChannel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
System.out.printf("(%1$s)[===>%2$s ] %3$s\n", "S", EXCHANGE_NAME + ":", message);
if (i == 4) {
latch.countDown();
}
}
senderChannel.close();
} catch (Exception e) {
}
}
}).start(); final Channel consumerChannel1 = connection.createChannel();
consumerChannel1.queueDeclare("SystemA", false, false, true, null);
consumerChannel1.queueBind("SystemA", EXCHANGE_NAME, "");
consumerChannel1.basicQos(3);
Consumer consumer1 = new DefaultConsumer(consumerChannel1) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.printf(" [ %2$s<===](%1$s) %3$s\n", "A", "SystemA", message);
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
}
consumerChannel1.basicAck(envelope.getDeliveryTag(), false);
}
};
consumerChannel1.basicConsume("SystemA", false, consumer1); latch.await();
final Channel consumerChannel2 = connection.createChannel();
consumerChannel2.queueDeclare("SystemB", false, false, true, null);
consumerChannel2.queueBind("SystemB", EXCHANGE_NAME, "");
consumerChannel2.basicQos(3);
Consumer consumer2 = new DefaultConsumer(consumerChannel2) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.printf(" [ %2$s<===](%1$s) %3$s\n", "B -- won't receive first 4 messages", "SystemB", message);
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
}
consumerChannel2.basicAck(envelope.getDeliveryTag(), false);
}
};
consumerChannel2.basicConsume("SystemB", false, consumer2);
}
}

代码第11行申明了名字叫 StatusUpdateFanout 的 fanout 类型 Exchange。

第33行申明了 SystemA 队列,第34行将 SystemA 队列绑定到 StatusUpdateFanout Exchange。注意到绑定路由键为空,路由键对于 fanout 类型 Exchange 无意义。

同理,第20行代码发送消息时,也不用设置路由键。所有发向 fanout 类型 Exchange 的消息都会无视路由键,广播给每个绑定队列。

B. 用 Topic 实现发布订阅

参考资料:https://www.rabbitmq.com/tutorials/tutorial-five-java.html

Topic 类型的 Exchange 通过支持通配符的路由键管理复杂的发布订阅关系。

发送消息时指定的路由键必须是点号(.)分隔的单词,例如 sourceA.statusUpdate.systemA。

队列绑定 Exchange 时指定的路由键可以使用通配符:

  • *(星号)替代一个单词
  • #(井号)替代 0~n 个单词

对每一条消息,Exchange 会遍历所有的绑定关系,确认消息指定的路由键(例如 sourceA.statusUpdate.systemA)是否匹配绑定关系中的路由键,如果匹配,则将消息推送到相应队列(例如 sourceA.statusUpdate.systemA、*.*.systemA、*.statusUpdate.* 和 sourceA.# 都匹配,但是 sourceB.# 和 *.systemA 都不匹配)。

gordon.study.rabbitmq.topic.Topic.java

senderChannel.exchangeDeclare(EXCHANGE_NAME, "topic");

consumerChannel1.queueBind("SystemA", EXCHANGE_NAME, "#.SystemA");

consumerChannel2.queueBind("SystemB", EXCHANGE_NAME, "*.*.SystemB");

senderChannel.basicPublish(EXCHANGE_NAME, "preOrder.statusUpdate.SystemA", null, message.getBytes("UTF-8"));

C. 没有历史数据?

对于中途创建的队列(例如上面的 SystemB 队列),是没有办法获得之前的消息的。但是如果队列提前创建好,就算没有消费者,队列里依然会有全量的数据。

RabbitMQ入门_07_Fanout 与 Topic的更多相关文章

  1. RabbitMQ入门(5)——主题(Topic)

    前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...

  2. RabbitMQ入门-Topic模式

    上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...

  3. RabbitMQ入门:主题路由器(Topic Exchange)

    上一篇博文中,我们使用direct exchange 代替了fanout exchange,这次我们来看下topic exchange. 一.Topic Exchange介绍 topic exchan ...

  4. RabbitMQ入门-消息订阅模式

    消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...

  5. RabbitMQ入门与使用篇

    介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀 ...

  6. RabbitMQ入门:总结

    随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...

  7. RabbitMQ入门:发布/订阅(Publish/Subscribe)

    在前面的两篇博客中 RabbitMQ入门:Hello RabbitMQ 代码实例 RabbitMQ入门:工作队列(Work Queue) 遇到的实例都是一个消息只发送给一个消费者(工作者),他们的消息 ...

  8. RabbitMQ入门(3)——发布/订阅(Publish/Subscribe)

    在上一篇RabbitMQ入门(2)--工作队列中,有一个默认的前提:每个任务都只发送到一个工作人员.这一篇将介绍发送一个消息到多个消费者.这种模式称为发布/订阅(Publish/Subscribe). ...

  9. .NET 环境中使用RabbitMQ RabbitMQ与Redis队列对比 RabbitMQ入门与使用篇

    .NET 环境中使用RabbitMQ   在企业应用系统领域,会面对不同系统之间的通信.集成与整合,尤其当面临异构系统时,这种分布式的调用与通信变得越发重要.其次,系统中一般会有很多对实时性要求不高的 ...

随机推荐

  1. 非线性方程(组):MATLAB内置函数 solve, vpasolve, fsolve, fzero, roots [MATLAB]

    MATLAB函数 solve, vpasolve, fsolve, fzero, roots 功能和信息概览 求解函数 多项式型 非多项式型 一维 高维 符号 数值 算法 solve 支持,得到全部符 ...

  2. 利用lodop打印控件轻松实现批量打印 (转载http://www.thinkphp.cn/topic/13085.html)

    最近在做一个打印程序,要实现批量打印功能,在网上找了很多天,也在tp官网咨询大牛们,对大家的的提议我一一进行了研究,总结如下: 要实现批量打印可以有两个办法: 一是利用专业的报表程序,能实现十分复杂的 ...

  3. yii的url写法

    Yii 各种url地址写法 echo Url::home(); 生成入口地址/yii2test/frontend/web/index.php: echo  Url::base();生成入口文件夹地址: ...

  4. python3 列表的常用方法

    Python3中常用的列表方法(method) 见:help(list) 方法 意义 L.index(v [, begin[, end]]) 返回对应元素的索引下标, begin为开始索引,end为结 ...

  5. linux常用命令:diff 命令

    diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...

  6. quartz-job实现定时任务配置

    使用quartz开源调度框架,写服务实现在一些指定场景发送特定短信,创建一个实现org.quartz.Job接口的java类.Job接口包含唯一的方法: public void execute(Job ...

  7. 好用的firefox浏览器、geckodriver驱动的版本组合(55 和 0.19.1)

    试过很多的firefox浏览器版本和geckodriver的组合,有时候好用,有时候不好用,现在确定了一个好用的版本组合,记录一下: firefox:版本55,而且此版本可以用firebug geck ...

  8. Python3 itchat实现微信定时发送群消息

    Python3 itchat实现微信定时发送群消息 一.简介 1,使用微信,定时往指定的微信群里发送指定信息. 2,需要发送的内容使用excel进行维护,指定要发送的微信群名.时间.内容. 二.py库 ...

  9. 计算两个集合的差集——第六期 Power8 算法挑战赛

    第六期Power8大赛 1.1 比赛题目 题目: 计算两个集合的差集: 详细说明: 分别有集合A和B两个大数集合,求解集合A与B的差集(A中有,但B中无的元素),并将结果保存在集合C中,要求集合C中的 ...

  10. ajax请求的同步异步问题

    前言 在做项目的过程中遇到一个bug就是:使用了alert语句后,代码才能正确执行,没使用就执行不成功. 后来我就用把console.log,代码就不能正确执行. 于是我就去比较了下consol.lo ...