工作中用到 RabbitMQ,但是RabbitMQ 官方的 Tutorials 是英文 Python 和 Jave 的,官网的教程很好,正好最近业余在撸 Python,所以直接来搞个 PHP 版本的,仅供 PHP 菜鸟一起来入门学习,如有错误和问题,欢迎留言或者邮件交流和指正。 首先申明中文并非我翻译的,要感谢这篇博文 **RabbitMQ 中文入门教程 ** 中对官方的翻译。 所有的示例代码请移步:https://github.com/yuansir/rabbitmq-tutorial-php-demo 转载请注明: 转载自Ryan 是菜鸟 | LNMP 技术栈笔记 如果觉得本篇文章对您十分有益,何不 打赏一下 本文链接地址: PHP 版 RabbitMQ 官方中文入门教程 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

阅读全文

路由(Routing) 在前面的教程中,我们实现了一个简单的日志系统。可以把日志消息广播给多个接收者。 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集。例如,我们只需要把严重的错误日志信息写入日志文件(存储到磁盘),但同时仍然把所有的日志信息输出到控制台中 绑定(Bindings) 前面的例子,我们已经创建过绑定(bindings),代码如下: $exchange->publish($message, ''); 绑定(binding)是指交换器(exchange)和队列(queue)的关系。可以简单理解为:这个队列(queue)对这个交换器(exchange)的消息感兴趣。 绑定的时候可以带上一个额外的 routing_key 参数。为了避免与 basic_publish 的参数混淆,我们把它叫做 binding key。以下是如何创建一个带 binding key 的绑定。 $exchange->publish($message, $routeKey); binding key 的含义取决于交换器(exchange)的类型。我们之前使用过的 fanout 类型会忽略这个值。 Direct 类型的交换器(exchange) 我们的日志系统广播所有的消息给所有的消费者(consumers)。我们打算扩展它,使其可以能够精确的过滤消息。例如我们也许值是希望当接收到一个严重的错误的时候才把消息写入磁盘,以免浪费磁盘空间。 我们使用的 fanout 类型的交换器(exchange)扩展性不够——它能做的仅仅是广播。 我们将会使用 direct 类型的交换器(exchange)来代替。路由的算法很简单——交换器将会对 binding key 和 routing key 进行精确匹配,从而确定消息该分发到哪个队列。 下图能够很好的描述这个场景: 在这个场景中,我们可以看到 direct exchange X 和两个队列绑定了。第一个队列使用 orange 作为 binding key,第二个队列有两个绑定,一个使用 black 作为 binding key,另外一个是 green。 这样以来,当 routing key 为 orange 的消息发布到交换器(exchange),就会被路由到队列 Q1。routing key 为 black 或者 green 的消息就会路由到 Q2。其他的所有消息都将会被丢弃。

阅读全文

发布/订阅 在上篇教程中,我们搭建了一个工作队列。每个任务之分发给一个工作者(worker)。在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers)。这种模式被称为“发布/订阅”。 为了描述这种模式,我们将会构建一个简单的日志系统。它包括两个程序——第一个程序负责发送日志消息,第二个程序负责获取消息并输出内容。 在我们的这个日志系统中,所有正在运行的接收方程序都会接受消息。我们用其中一个接收者(receiver)把日志写入硬盘中,另外一个接受者(receiver)把日志输出到屏幕上。 最终,日志消息被广播给所有的接受者(receivers)。 交换器(Exchanges) 前面的教程,我们发送消息到队列并从中取出消息。现在是时候介绍 RabbitMq 中完整的消息模型了。 让我们简单的概括一下之前的教程: *发布者(producer)*是发布消息的应用程序。 *队列(queue)*用于消息存储的缓冲。 *消费者(consumer)*是接收消息的应用程序。 RabbitMQ 消息模型的核心理念是:发布者(producer)不会直接发送任何消息给队列。事实上,发布者(producer)甚至不知道消息是否已经被投递到队列。 发布者(producer)只需要把消息发送给一个*交换器(exchange)*。交换器非常简单,它一边从发布者方接收消息,一边把消息推入队列。交换器必须知道如何处理它接收到的消息,是应该推送到指定的队列还是是多个队列,或者是直接忽略消息。这些规则是通过*exchange type*来定义的。 有几个可供选择的交换器类型:AMQP_EX_TYPE_DIRECT, AMQP_EX_TYPE_FANOUT,AMQP_EX_TYPE_HEADER or AMQP_EX_TYPE_TOPIC。我们在这里主要说明AMQP_EX_TYPE_FANOUT。先创建一个 fanout 类型的交换器,命名为 logs: $exchange->setName('logs'); $exchange->setType(AMQP_EX_TYPE_FANOUT); $exchange->declare(); fanout 交换器很简单,你可能从名字上就能猜测出来,它把消息发送给它所知道的所有队列。这正是我们的日志系统所需要的。 交换器列表 rabbitmqctl 能够列出服务器上所有的交换器: > $ sudo rabbitmqctl list_exchanges > Listing exchanges ... > logs fanout > amq.direct direct > amq.topic topic > amq.fanout fanout > amq.headers headers > ...done. > ``` > > 这个列表中有一些叫做 amq.\*的交换器。这些都是默认创建的,不过这时候你还不需要使用他们。 > > #### 匿名的交换器 > > ~~前面的教程中我们对交换器一无所知,但仍然能够发送消息到队列中。因为我们使用了命名为空字符串(“”)默认的交换器。~~ > > ~~回想我们之前是如何发布一则消息:~~ > > ``` > $exchange->publish($message, $routeKey); > ``` > > ~~exchange 参数就是交换器的名称。空字符串代表默认或者匿名交换器:消息将会根据指定的 routing_key 分发到指定的队列。~~ > > **在 PHP 的 AMQP 中如果 exchange 设置为匿名的话,是报错的:PHP Fatal error: Uncaught exception ‘AMQPExchangeException’ with message ‘Invalid exchange name given, must be between 1 and 255 characters long.

阅读全文

工作队列 在第一篇教程中,我们已经写了一个从已知队列中发送和获取消息的程序。在这篇教程中,我们将创建一个工作队列(Work Queue),它会发送一些耗时的任务给多个工作者(Works )。 工作队列*(又称:任务队列——Task Queues)是为了避免等待一些占用大量资源、时间的操作。*当我们把*任务(Task)*当作消息发送到队列中,一个运行在后台的工作者(worker)进程就会取出任务然后处理。当你运行多个工作者(workers),任务就会在它们之间共享。 这个概念在网络应用中是非常有用的,它可以在短暂的 HTTP 请求中处理一些复杂的任务。 准备 之前的教程中,我们发送了一个包含“Hello World!”的字符串消息。现在,我们将发送一些字符串,把这些字符串当作复杂的任务。我们没有真是的例子,例如图片缩放、pdf 文件转换。所以使用 sleep()函数来模拟这种情况。我们在字符串中加上点号(.)来表示任务的复杂程度,一个点(.)将会耗时 1 秒钟。比 如”Hello…”就会耗时 3 秒钟。 我们对之前教程的*send.php*做些简单的调整,以便可以发送随意的消息。这个程序会按照计划发送任务到我们的工作队列中。我们把它命名为 new_task.php: $message = empty($argv[1]) ? 'Hello World!' : ' '.$argv[1]; $exchange->publish($message, $routeKey); var_dump("[x] Sent $message"); 我们的旧脚本(_receive.php_)同样需要做一些改动:它需要为消息体中每一个点号(.)模拟 1 秒钟的操作。它会从队列中获取消息并执行,我们把它命名为 worker.php: function callback($envelope, $queue) { $msg = $envelope->getBody(); var_dump(" [x] Received:" . $msg); sleep(substr_count($msg,'.')); $queue->ack($envelope->getDeliveryTag()); } 轮询分发 使用工作队列的一个好处就是它能够并行的处理队列。如果堆积了很多任务,我们只需要添加更多的工作者(workers)就可以了,扩展很简单。 首先,我们先同时运行两个 worker.php 脚本,它们都会从队列中获取消息,到底是不是这样呢?我们看看。 你需要打开三个终端,两个用来运行 worker.php 脚本,这两个终端就是我们的两个消费者(consumers)—— C1 和 C2。 shell1 $php worker.

阅读全文

RabbitMQ 是一个消息代理。它的核心原理非常简单:接收和发送消息。你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处。在这个比喻中,RabbitMQ 是一个邮箱、邮局、邮递员。RabbitMQ 和邮局的主要区别是,它处理的不是纸,而是接收、存储和发送二进制的数据——_消息_。一般提到 RabbitMQ 和消息,都用到一些专有名词。 *生产(Producing)*意思就是发送。发送消息的程序就是一个*生产者(producer)*。我们一般用”P”来表示: *队列(queue)*就是邮箱的名称。消息通过你的应用程序和 RabbitMQ 进行传输,它们能够只存储在一个*队列(queue)*中。 *队列(queue)*没有任何限制,你要存储多少消息都可以——基本上是一个无限的缓冲。多个*生产者(producers)*能够把消息发送给同一个队列,同样,多个*消费者(consumers)*也能攻从一个*队列(queue)*中获取数据。队列可以化城这样(图上是队列的名称): *消费(Consuming)*和获取消息是一样的意思。一个*消费者(consumer)*就是一个等待获取消息的程序。我们把它画作”C”: Hello World! (使用 pika 0.9.5 Python 客户端) 我们的“Hello world”不会很复杂——仅仅发送一个消息,然后获取它并输出到屏幕。这样以来我们需要两个程序,一个用作发送消息,另一个接受消息并打印消息内容 我们大体的设计是这样的: 生产者(Producer)把消息发送到一个名为“hello”的队列中。消费者(consumer)从这个队列中获取消息。 RabbitMQ 库 RabbitMQ 使用的是 AMQP 协议。要使用她你就必须需要一个使用同样协议的库。几乎所有的编程语言都有可选择的库。python 也是一样,可以从以下几个库中选择: py-amqplib txAMQP pika 在这一系列教程中,我们打算使用PHP 的AMQP扩展。详细教程请查看: mac os 下 RabbitMq 以及 PHP amqp 扩展安装记录 发送消息 我们第一个程序 send.php 会发送一个消息到队列中。首先要做的事情就是建立一个到 RabbitMQ 服务器的连接。 $connection = new AMQPConnection(array('host' =>'127.0.0.1', 'port' =>'5672', 'vhost' =>'/', 'login' =>'guest', 'password' => 'guest')); 现在我们已经连接上服务器了,那么,在发送消息之前我们需要确认队列是存在的。如果我们把消息发送到一个不存在的队列,RabbitMQ 会丢弃这条消息。我门先创建一个名为*hello*的队列,然后把消息发送到这个队列中。

阅读全文

记录一下安装配置的过程,这里我都是直接用 brew 来安装,如果没有安装先安装: /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)" 1.首先就是安装 rabbitmq 了,简单,因为 rabbitmq 是依赖 erlang,所以安装中会下载并且安装 erlang,下载编译时间可能会有点长,稍安勿躁: brew update brew install rabbitmq 2.安装 rabbitmq-c,C 与 RabbitMQ 通信需要依赖 rabbitmq-c 库(librabbitmq),具体请看https://github.com/alanxz/rabbitmq-c: git clone git://github.com/alanxz/rabbitmq-c.git mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. cmake --build . --target install 3.接下来就是安装 php amqp 的扩展了: 你可以源码编译安装 wget http://pecl.php.net/get/amqp-1.0.0.tgz tar zxvf amqp-1.0.0.tgz cd amqp-1.0.0 /usr/local/php/bin/phpize ./configure –with-php-config=/usr/local/php/bin/php-config –with-amqp make && make install 当然也可以直接用 PECL 来装, 如果还没有安装 pear 的话:

阅读全文

最近在学习 Python,正好也可以巩固提高一下 Python! 运行系统 ubuntu 12.04,rabbitmq 版本是 2.7.1,python 版本是 2.7.3。 因为笔记里提到一些名词,虽然叫法不一样,不过都是表达同样的事物,所以有必要先说明下,以免产生疑惑。主要是两个名词: producer 直译为生成者,就是产生消息的东东,笔记里提到的发送者、发送端都是一个意思。如果把消息比喻成任务,也可以理解为任务分配者。 consumer 直译为消费者,就是接收消息的东东 ,笔记里提到的接收者、接收端都是一个意思。如果把消息比喻成任务,也可以理解为工作者。 1、ubuntu 安装 rabbitmq 和 python 的使用实现 这篇主要记录了在 ubuntu 下安装 rabbitmq 服务的过程和安装 python pika 库的过程,并演示了单向发送消息的工作方式。 2、python 使用 rabbitmq 实例二,工作队列 继上一篇,演示了多个接收端情况下,消息发送的工作方式。 3、python 使用 rabbitmq 实例三,交换机 前面两篇的示例,都只使用了一个队列,消息是依次发送给绑定到该队列的接收端。如果要广播出去,就要使用交换机,本篇演示了交换机的工作方式。 4、python 使用 rabbitmq 实例四,路由键 第三篇的消息是广播出去的,所有接收端都会接收到,如果要精确指明消息的接收端,就要使用路由键,本篇主要演示了路由键的工作方式。 5、python 使用 rabbitmq 实例五,路由键模糊匹配 第四篇的路由键是精确匹配的,有时用需要模糊匹配,本篇主要演示了路由键模糊匹配的工作方式。 6、python 使用 rabbitmq 实例六,远程结果返回 前面五篇的消息都是发送出去就完事了,接收端并没有将结果返回给发送端。有些情况下需要接收端将接收到的消息处理后再返回给发送端,本篇演示了这种情况的处理方式。 7、python 使用 rabbitmq 实例七,相互关联编号 correlation id 上一篇只是发送单条消息,返回的结果自然是对应该条消息,但是如果同时发出多条消息,就会返回多个结果,如何将发送的消息和返回的结果一一对应起来呢?本篇演示了 correlation id 的工作方式,就是用来解决这个问题的。 转载请注明: 转载自Ryan 是菜鸟 | LNMP 技术栈笔记

阅读全文

作者的图片

Ryan是菜鸟 | LNMP技术栈笔记

一步一个脚印,一直在路上!记录LNMP技术栈,Web架构,区块链等笔记

菜鸟码农

南京