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

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

之前我们在原理中介绍了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. PostGIS中生成GUID字段值

    create extension "uuid-ossp" update base_region set region_id = uuid_generate_v4() update ...

  2. Android View体系(一)视图坐标系

    前言 Android View体系是界面编程的核心,他的重要性不亚于Android四大组件,在这个系列中我会陆续讲到View坐标系.View的滑动.View的事件分发等文章来逐步介绍Android V ...

  3. 【Java入门提高篇】Day23 Java容器类详解(六)HashMap源码分析(中)

    上一篇中对HashMap中的基本内容做了详细的介绍,解析了其中的get和put方法,想必大家对于HashMap也有了更好的认识,本篇将从了算法的角度,来分析HashMap中的那些函数. HashCod ...

  4. TERADATA数据库操作

    1.创建一个数据库的命令举例: ,spool; 注释:该命令创建了一个测试数据库testbase,其永久表空间为200mb,spool空间不能超过100mb.在teradata数据库系统的缺省方式下, ...

  5. 安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details"错误.原因是启动"VisualSVN Server"失败

    安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server ...

  6. CSS网页菜单

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserContro ...

  7. input子系统事件处理层(evdev)的环形缓冲区【转】

    在事件处理层(evdev.c)中结构体evdev_client定义了一个环形缓冲区(circular buffer),其原理是用数组的方式实现了一个先进先出的循环队列(circular queue), ...

  8. yum-config-manager命令找不到

    安装: 命令在yum-utils 包里,安装既可以解决:yum -y install yum-utils 当然你也可以通过 dnf 替代 dnf 命令替代: 禁用仓库命令就是: dnf config- ...

  9. 通过logstash过滤、分析日志数据

    logstash是怎么工作的呢? Logstash是一个开源的.服务端的数据处理pipeline(管道),它可以接收多个源的数据.然后对它们进行转换.最终将它们发送到指定类型的目的地.Logstash ...

  10. Python getting started guide

    Get up in the morning. The first thing is to write a blog, although it uses machine translation, it ...