之前的学习中,我们了解的工作队列实现的是:一个消息只发送到一个消费者。

现在我们来学习一下新模式:发布/订阅模式

之前我们在原理中介绍了exchange,但好像并没有使用。而是直接往队列里发消息和取消息。现在我们使用rabbitmq的消息模型,利用交换机来转发消息。

首先我们来了解一下exchange的四种类型:fanout、direct、topic、headers

fanout:

 

  1、消息与队列匹配规则:该类型交换机会将收到的消息广播给所有与之绑定的队列

  2、该情况下,生产者只关系消息发送到哪个交换机,由交换机决定消息发送到哪些队列。而消费者只关系订阅哪个队列

direct:

  

  1、消息分发规则:消息会被推送至绑定键(binding key)和消息发布附带的路由键(routing key)完全匹配的消息

  2、图示说明:消息1附带路由键“error”、与绑定键“error”匹配,而队列Q4、Q5与交换机X间都存在绑定键“error”所以消息1被分发到Q4、Q5;消息2附带路由键“info”,而队列Q4与交换机间存在绑定建“info”,所以消息2被分发到队列Q4。

  3、分发到队列的消息不再带有发送者的任何信息,如果消息实体里包含了发送者的信息,那么消费者可以获取发送者信息

topic:

  

  1、消息分发规则:一个附带特殊的路由键(routing key)会被转发到绑定键(binding key)与之匹配的队列中

  2、routing key与binding key匹配规则: routing key必须是由点隔开的一系列的标识符组成。标识符可以是任何东西,但一般都与消息的某些特效有关。如:"stock.usd.nyse","nyse.vmw","quick.orange.rabbit"。上限为255字节。 绑定键与选择键形式一样。 两种特殊情况:*匹配一个标识符、#匹配0个或多个标识符

  3、图示说明:  消息1附带路由键“fast.orange.*”与绑定键“#”、“*.orange.*”匹配,所以消息1被分发给队列Q6、Q7;消息2附带路由键“lazy.orange.a.b”与绑定键“#”、“lazy.#”匹配,所以消息2被分发给队列Q6、Q8。

headers:

 

  1、消息分发规则: headers类型的交换机发消息不依赖routing key。而是使用发消息时basicProperties对象中的headers匹配。headers是一个键值对类型。发送者发消息时将这些键值对放在basicProperties对象的headers字段中。队列绑定交换机时绑定一些键值对。两者匹配时。队列就可以收到消息。

    匹配模式有两种:

     在队列绑定到交换机时用x-match来指定,all代表定义的多个键值对都要满足,any代表只要满足一个就可以。fanout,direct,topic中的routing 可以需要字符串,而headers没有这个要求。键值对可以是任何类型。

  2、图示说明:  消息1附带的键值对与Q9绑定键值对的color匹配、speed不匹配,但是Q9的x-match设置为any,因此只要有一项匹配消息1就可以被分发到Q9。消息1与Q10完全匹配,消息2与Q10部分匹配,由于Q10的x-match设置为all,所以只能接受到消息1。

案例:创建一个简单的日志系统,有两个程序组成:一个输出日志消息,一个接收并打印日志消息

  在该系统中,每一个cusumer都会接到所有消息,其中一个cusumer直接保存消息到磁盘,另一个cusumer输出消息

  在该案例中,我们使用fanout类型的exchange,通过 channel.exchangeDeclare("logs,"fanout")来设置参数

  在rabbitmq中,默认的exchange的名字是空字符串。

在coding之前我们还要了解一下些小知识:

  临时队列:

    当我们指定了特定名字的队列时,我们要让消费者指向同一个队列。当生产者消费者共用一个队列时。队列名字非常重要。 对于本案例的日志系统而言,我们想让每个消费者都接到所有的日志消息。而不是其中一部分。我们关心的是当前广播的消息而不是之前的。所以我们要做两件事情满足我们的要求:

  1、我们连接rabbitmq服务时,需要一个新鲜的空的队列。我们自定义随机名,更好的是让rabbitmq服务器为我们的队列随机起名

  2、当我们关闭消费者时,队列应该自动删除

  如何创建队列名呢?

    String queueName = channel.queueDeclare().getQueue();

    这样可以获取随机的队列名 调用无参的queueDeclare方法时,就创建一个非持久、独特的会自动删除的队列

  绑定:

   我们创建了一个fanout类型的exchange和一个队列。我们需要告诉exchange发送消息到我们的队列。exchange与队列之间的关系称为绑定(binding)。    

   channel.queueBind(queueName,"logs",""); 这样我们就将创建的队列和exchange建立了关系。

   exchange会将消息发送到这个队列 rabbitmqctl list_binding 查看所有已经存在的绑定关系

Coding一下,你就知道

producer:

cusumer: 

在这个模式下:

  对于producer而言,我们将消息发送给logs交换机,而不是无名的交换机。发消息时我们提供一个路由键routing key。但它的值会被fanout类型的交换机忽略。

  如果路由器还没有绑定队列,这些发送给路由器的消息将会丢失。但这对我们无所谓,如果还没有cusumer监听,我们可以安全地丢弃这些消息。

RabbmitMQ-Publish/Subscribe的更多相关文章

  1. 使用Guava EventBus构建publish/subscribe系统

    Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发.在系统中,Subscribers ...

  2. 【RabbitMQ】Publish/Subscribe

    Publish/Subscribe 在上一节我们创建了一个work queue.背后的设想为每个任务被分发给明确的消费者.这节内容我们将做一些完全不同的事情 -- 我们将发送一条消息给多个消费者.这种 ...

  3. publish/subscribe

    Pub/Sub功能 Pub/Sub功能(means Publish, Subscribe)即发布及订阅功能.基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供 ...

  4. Mina、Netty、Twisted一起学(七):发布/订阅(Publish/Subscribe)

    消息传递有很多种方式,请求/响应(Request/Reply)是最常用的.在前面的博文的例子中,很多都是采用请求/响应的方式,当服务器接收到消息后,会立即write回写一条消息到客户端.HTTP协议也 ...

  5. RabbitMQ(三) -- Publish/Subscribe

    RabbitMQ(三) -- Publish/Subscribe `rabbitmq`支持一对多的模式,一般称为发布/订阅.也就是说,生产者产生一条消息后,`rabbitmq`会把该消息分发给所有的消 ...

  6. ZeroMQ之Publish/Subscribe (Java)

    前面的文章介绍了比较简单的Request/Subscribe模式, 这篇文章介绍更为经典的Publish/Subscribe通信模式用来ZeroMQ的实现,其通信方式如下图: 客户端(subscrib ...

  7. RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  8. (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)

    上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...

  9. 【转】Difference between Point-To-Point and Publish/Subscribe JMS Messaging Models

    Difference between Point-To-Point and Publish/Subscribe JMS Messaging Models   Point-to-Point (PTP) ...

  10. javascript设计模式——Publish/Subscribe

    推荐阅读http://dev.housetrip.com/2014/09/15/decoupling-javascript-apps-using-pub-sub-pattern/ 我们先引出问题的所在 ...

随机推荐

  1. 去除git版本控制

    命令:find . -name ".git" | xargs rm –Rf linux $ find . -type d -iname '__pycache__' -exec rm ...

  2. ArcGIS for Server 的修改IP问题

      ArcGIS for Server 的修改IP问题   1. [arcgisserver@centos6 ~]$ vi /home/arcgisserver/serverconfig/config ...

  3. Android View体系(六)从源码解析Activity的构成

    前言 本来这篇是要讲View的工作流程的,View的工作流程主要指的measure.layout.draw这三大流程,在讲到这三大流程之前我们有必要要先了解下Activity的构成,所以就有了这篇文章 ...

  4. Kotlin入门(10)七十二变的输入参数

    上一篇文章介绍了Kotlin对函数的基本用法,包括函数的定义.输入参数的声明.输出参数的声明等等,这些足够对付简单的场合了.当然了,倘若一门新语言仅仅满足于这些雕虫小技,那也实在没什么前途.既然Kot ...

  5. Python中For循环

    1. for i in range(10): print(i) 输出结果 F:\py\pyProject\venv\Scripts\python.exe F:/py/pyProject/venv/wh ...

  6. HTML 5 <input> list 属性

    定义和用法 list 属性引用数据列表,其中包含输入字段的预定义选项. 可以用来做关联搜素

  7. 高通GPIO驱动(DTS方式)

    gpio调试的方式有很多,linux3.0以上ARM架构的处理器基本上都采用了DTS的方式,在linux3.0可以通过获取sysfs的方式来获取gpio状态: sysfs文件系统的建立可以参照下面的博 ...

  8. 【PAT】B1082 射击比赛(20 分)

    水提水题,直接贴代码啦 #include<cstdio> #include<algorithm> using namespace std; struct ppp{ int id ...

  9. tkinter学习系列之(七)Frame与Labelframe 控件

    目录 目录 前言 (一)Frame (二)Labelframe 目录 前言 Frame与Labelframe都是容器,用来存放其他控件,也是用来更好的管理布局. 我一般是用来存放一组相关的控件,让Fr ...

  10. ubuntu 14.04安装zabbix3.0以及汉化

    文章出处借鉴于 http://www.cnblogs.com/-10086/p/5317524.html 1.下载deb # wget http://repo.zabbix.com/zabbix/3. ...