一、发布/订阅

分发一个消息给多个消费者(consumers)。这种模式被称为“发布/订阅”。

为了描述这种模式,我们将会构建一个简单的日志系统。它包括两个程序——第一个程序负责发送日志消息,第二个程序负责获取消息并输出内容。

在这个日志系统中,所有正在运行的接收方程序都会接受消息。我们用其中一个接收者(receiver)把日志写入硬盘中,另外一个接受者(receiver)把日志输出到屏幕上。

最终,日志消息被广播给所有的接受者(receivers)。

二、交换器(Exchanges)

  • 发布者(producer)是发布消息的应用程序。
  • 队列(queue)用于消息存储的缓冲。
  • 消费者(consumer)是接收消息的应用程序。

RabbitMQ消息模型的核心理念是:发布者(producer)不会直接发送任何消息给队列。事实上,发布者(producer)甚至不知道消息是否已经被投递到队列。

发布者(producer)只需要把消息发送给一个交换器(exchange)。交换器非常简单,它一边从发布者方接收消息,一边把消息推入队列。交换器必须知道如何处理它接收到的消息,是应该推送到指定的队列还是是多个队列,或者是直接忽略消息。这些规则是通过exchange type来定义的。

有几个可供选择的交换器类型:

AMQPEXTYPEDIRECT

AMQPEXTYPEFANOUT

AMQPEXTYPEHEADER  or AMQPEXTYPETOPIC

这里主要说明AMQPEXTYPE_FANOUT。先创建一个fanout类型的交换器,命名为logs:

$exchange->setName('logs');
$exchange->setType(AMQP_EX_TYPE_FANOUT);
$exchange->declareExchange();

fanout交换器很简单,你可能从名字上就能猜测出来,它把消息发送给它所知道的所有队列。这正是我们的日志系统所需要的。

现在,我们就可以发送消息到一个具名交换器了:

$exchange->publish($message, '');

三、临时队列

给一个队列命名是很重要的——我们需要把工作者(workers)指向正确的队列。如果你打算在发布者(producers)和消费者(consumers)之间共享同队列的话,给队列命名是十分重要的。

但是这并不适用于我们的日志系统。我们打算接收所有的日志消息,而不仅仅是一小部分。我们关心的是最新的消息而不是旧的。为了解决这个问题,我们需要做两件事情。

首先,当我们连接上RabbitMQ的时候,我们需要一个全新的、空的队列。我们可以手动创建一个随机的队列名,或者让服务器为我们选择一个随机的队列名(推荐)。我们只要在调用$queue->declareQueue();方法的时候,不提供queue参数就可以了:

$queue = new AMQPQueue($channel);
$queue->setFlags(AMQP_EXCLUSIVE);
$queue->declareQueue();

这时候我们可以通过$queue->getName();获得已经生成的随机队列名。它可能是这样子的:amq.gen-U0srCoW8TsaXjNh73pnVAw==。

第二步,当与消费者(consumer)断开连接的时候,这个队列应当被删除。我们可以使用exclusive标识。$queue->setFlags(AMQP_EXCLUSIVE);

四、绑定

我们已经创建了一个fanout类型的交换器和一个队列。现在我们需要告诉交换器如何发送消息给我们的队列。交换器和队列之间的关系我们称之为绑定(binding)。

$queue->bind($exchangeName, $queue->getName());

现在,logs交换器将会把消息添加到我们的队列中。

五、代码整合

  1、生产者:send_log.php

  

<?php

/**
* PHP amqp(RabbitMQ) Demo-3
*/ $exchangeName = 'logs';
$message = empty($argv[1]) ? 'info:Hello World!' : ' '.$argv[1]; $connection = new AMQPConnection(array('host' => '127.0.0.1', 'port' => '5672', 'vhost' => '/', 'login' => 'guest', 'password' => 'guest'));
$connection->connect() or die("Cannot connect to the broker!\n"); $channel = new AMQPChannel($connection);
$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_FANOUT);//把消息发送给它所知道的所有队列
$exchange->declareExchange(); $exchange->publish($message, '');
var_dump("[x] Sent $message"); $connection->disconnect();

  2、消费者:receive_logs.php

  

<?php

/**
* PHP amqp(RabbitMQ) Demo-3
*/
$exchangeName = 'logs'; $connection = new AMQPConnection(array('host' => '127.0.0.1', 'port' => '5672', 'vhost' => '/', 'login' => 'guest', 'password' => 'guest'));
$connection->connect() or die("Cannot connect to the broker!\n"); $channel = new AMQPChannel($connection); $exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_FANOUT);//把消息发送给它所知道的所有队列
$exchange->declareExchange(); $queue = new AMQPQueue($channel);
$queue->setFlags(AMQP_EXCLUSIVE);//当与消费者(consumer)断开连接的时候,这个队列应当被删除
$queue->declareQueue();//创建一个随机的队列名
$queue->bind($exchangeName, ''); var_dump('[*] Waiting for messages. To exit press CTRL+C');
while (TRUE) {
$queue->consume('callback');
}
$connection->disconnect(); function callback($envelope, $queue) {
$msg = $envelope->getBody();
var_dump(" [x] Received:" . $msg);
$queue->nack($envelope->getDeliveryTag());
}

这样我们就完成了。如果你想把日志保存到文件中,只需要打开控制台输入:

$ php receive_logs.php > logs_from_rabbit.log

如果你想在屏幕中查看日志,那么打开一个新的终端然后运行:

$ php receive_logs.php

当然还要发送日志:

$ php send_log.php
 

RabbitMq学习4-发布/订阅(Publish/Subscribe)的更多相关文章

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

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

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

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

  3. RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)

    原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...

  4. (转) RabbitMQ学习之发布/订阅(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887733 参考:http://blog.csdn.NET/lmj623565791/artic ...

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

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

  6. RabbitMQ入门教程——发布/订阅

    什么是发布订阅 发布订阅是一种设计模式定义了一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有的订阅者对象,使他们能够自动更新自己的状态. 为了描述这种 ...

  7. 【Redis数据库】命令学习笔记——发布订阅、事务、脚本、连接等命令汇总

    本篇基于redis 4.0.11版本,学习发布订阅.事务.脚本.连接的相关命令. Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. 序号 ...

  8. rabbitmq消息队列——"发布订阅"

    三."发布订阅" 上一节的练习中我们创建了一个工作队列.队列中的每条消息都会被发送至一个工作进程.这节,我们将做些完全不同的事情--我们将发送单个消息发送至多个消费者.这种模式就是 ...

  9. RabbitMQ/JAVA (发布/订阅模式)

    发布/订阅模式即生产者将消息发送给多个消费者. 下面介绍几个在发布/订阅模式中的关键概念-- 1. Exchanges (转发器) 可能原来我们都是基于一个队列发送和接收消息.现在介绍一下完整的消息传 ...

  10. 4.RabbitMQ系列之发布/订阅模式

    我们把一个消息转发给多个消费者,这种模式称之为发布-订阅模式 1.交换器(Exchange) RabbitMq消息模式的核心思想是:一个生产者并不会直接往一个队列中发送消息,事实上,生产者根本不知道它 ...

随机推荐

  1. 原生js数组排序(封装方法)

    //两值互换 function Sort(arr, index){ //参数arr代表数组,index代表数组元素下标 arr[index] += arr[index + 1];  //a+=b; a ...

  2. python学习理论

    结论 其实学python这本书 不一定要全部敲一遍 在“”动手试一试“”里面 把这篇学到的东西测试一下就算是掌握了 要在实际工作场景当中使用还需要进一步练习这样做的话 比较好一点 边学边测试 加深掌握 ...

  3. 全方面了解和学习PHP框架PHP培训教程

    PHP成为最流行的脚本语言有许多原因:灵活性,易用性等等.对于项目开发来说,我们通常需要一个PHP框架来代替程序员完成那些重复的部分.本文,兄弟连PHP培训 将对PHP框架进行全面解析. PHP框架是 ...

  4. jquery animated选择器 语法

    jquery animated选择器 语法 作用::animated 选择器选取当前的所有动画元素.直线电机参数 语法:$(":animated") jquery animated ...

  5. css @keyframes属性 语法

    css @keyframes属性 语法 @keyframes是什么?直线电机生产厂家 @keyframes是CSS的一种规则,可以用来定义CSS动画的一个周期的行为,创建简单的动画. 作用:通过 @k ...

  6. Anaconda是如何进行版本管理的?

    创建不同的environments,在电脑中会有不同的文件夹 然后,当使用conda下载时,会下载到不同的env文件夹下(提前进行env切换) 那么不是在anaconda prompt命令行下下载的呢 ...

  7. FP回写阶段卡住或报错

    FP在autosap阶段往往会因各种各样的因素导致回写报错,卡住等异常: 本次由于一个视图的性能突然下降导致回写长期卡住没有完成: 这时如果要重新执行回写的话就要检查哪部分的数据回写到SAP端,一般有 ...

  8. 利用pymysql同时修改两张表的数据

    使用pymysql操作数据库中相关联的两张表需求:两张表中分别有一个字段是json格式,需要往json中再插入一个属性值’container_cloud’=’fasle’. import pymysq ...

  9. iterator删除元素

    总结 在需要的删除等操作时,不能使用简单的foreach,因为其底层依然用的是Iterator,但是调用的是集合中的remove方法. 使用迭代器对象调用其中的remove方法,以保证线程同步.

  10. Vue/Element-ui 安装搭建开发环境(一)

    Element 是饿了么全段开发团队推出的一套基于 vue.js2.0 的 PC Web 端开发框架. Element 中文文档:https://element.eleme.cn/#/zh-CN 1. ...