RabbitMQ官网教程翻译(PHP版本)_4

本文所有内容均个人从RabbitMQ官网教程中翻译,若图片文字的引用有任何侵权的地方,联系我,我会立马删除。

This article was translated from RabbitMQ Official Tutorials by myself,and if this article and the images in this article have any infringement,please contact to me, and i will delete them.

路由

(使用php-amqplib
在上一个教程我们建立了一个简单的日志系统。我们已经能够把日志消息广播到许多接收者。

在这个教程中,我们准备为这个消息系统添加一个特性——让它能够仅订阅消息中的一个子集。例如,我们将能够把关键的错误信息记录到日志文件(保存到磁盘空间中),同时能够把所有的日志消息打印到控制台上。

绑定

上一个例子,我们已经(在路由器与Queue(队列)之间)建立了绑定。你可能还记得下面的代码:

$channel->queue_bind($queue_name,'logs');// 将队列绑定到logs路由上

一个绑定就是一个交换机(exchange)与一个Queue(队列)之间的关系。这可以简单地描述为:这个Queue(队列)对来自这个路由的消息感兴趣。

绑定可以携带一个额外的routing_key参数。为了避免与$channel::basic_publish的参数混淆(第三个也叫routing_key),我们准备称他为bingding_key。这是我们创建一个带有键的绑定的方式:

$binding_key = 'black';
$channel->queue_bind($queue_name, $exchange_name, $binding_key);

这意味着一个绑定键(binding key)取决于路由的类型。之前我们所使用的fanout类型的路由,简单地忽略了这个值。

直接交换(Direct exchange)

我们在上一个教程中的日志系统广播所有消息到所有的Consumer(消费者)。我们打算拓展它,让它可以根据消息的严重程度过滤消息。例如我们可能希望写日志的脚本仅把收到的严重错误的日志消息写到磁盘上,从而不把磁盘空间浪费在过多的警告或者信息类型的日志消息。

我们所使用的fanout交换机并不能提供给我们足够的灵活性——它只是盲目地广播。

我们将会使用一个direct类型的交换机来代替。direct类型交换机背后的路由算法(routing algorithm)是简单的——当Queue(队列)binding key与消息的routing key完全匹配的时候,这条消息才会进入对应的路由。

为了说明这种情况,参考一下下面的步骤:


direct route deliver message to queues by different binding key

在这个步骤中,我们可以看到direct类型的交换机X和绑定在它上面的两个Queue(队列)。第一个队列通过orange绑定键(binding key)来绑定,而第二个则拥有两个绑定,一个是通过black绑定键,另外一个是通过green绑定键。

在这样一个步骤中,一条带有orange路由键(routing key)的消息发送到交换机会被路由到Queue(队列)Q1。带有black或者green路由键的消息将会被路由到Q2。所有其他的消息将会被丢弃。

多重绑定

two queue binding on one direct route with the same binding key

用相同的键绑定多个Queue(队列)是完全合法的。在我们的例子中我们可以在XQ1之间通过black绑定键添加一个绑定。在这一情况,direct路由将会像fanout路由那样广播消息到所有匹配的Queue(队列)上。一条拥有black路由键的消息将会被同时分发到Q1Q2

发出日志

我们把这一模型使用在日志系统上。我们将发送消息到一个direct路由来代替fanout路由。我们将会把日志等级作为一个routing key。这样的话接收脚本将能够选择它想接收的严重等级。让我们先学习发出日志。

像往常一样,我们首先需要创建一个交换机。

$channel->exchange_declare('direct_logs', 'direct', false, false, false);

然后我们已经准备好发送一条消息了。

$channel->exchange_declare('direct_logs', 'direct', false, false, false);
$channel->basic_publish($msg, 'direct_logs', $severity);

为了简化,我们将会假定“severity”可以是“info”,“warning”,“error”中的一个。

订阅

接收消息与前面的教程类似,只不过我们准备为我们感兴趣的每一个日志等级(severity)创建一个新的绑定。

foreach($severities as $severity) {
    $channel->queue_bind($queue_name, 'direct_logs', $severity);
}

把他们一起运行

the complete mode

emit_log_direct.php类的代码如下:

<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

// 定义为direct模式路由
$channel->exchange_declare('direct_logs', 'direct', false, false, false);

// 从命令行接收参数作为日志等级,默认为info
$severity = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'info';

$data = implode(' ', array_slice($argv, 2));
if(empty($data)) $data = "Hello World!";

$msg = new AMQPMessage($data);

// 发送消息到对应的路由,并携带一个routing key
$channel->basic_publish($msg, 'direct_logs', $severity);

echo " [x] Sent ",$severity,':',$data," \n";

$channel->close();
$connection->close();
?>

receive_logs_direct.php的代码如下:

<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

// 定义为direct交换机并命名为direct_logs
$channel->exchange_declare('direct_logs', 'direct', false, false, false);

// 创建临时的非持久化的队列
list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);

$severities = array_slice($argv, 1);
if(empty($severities )) {
    file_put_contents('php://stderr', 
          "Usage: $argv[0] [info] [warning] [error]\n");
    exit(1);
}

foreach($severities as $severity) {
    // 绑定多个binding key
    $channel->queue_bind($queue_name, 'direct_logs', $severity);
}

echo ' [*] Waiting for logs. To exit press CTRL+C', "\n";

$callback = function($msg){
  echo ' [x] ',$msg->delivery_info['routing_key'], ':', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);

while(count($channel->callbacks)) {
    $channel->wait();
}

$channel->close();
$connection->close();
?>

如果你打算只保存"warning"与"error"(不包含"info")等级的日志消息到一个文件,只需要打开控制台并输入:

php receive_logs_direct.php warning error > logs_from_rabbit.log

如果你想在你的屏幕上查看所有的日志消息,只需要打开一个新的终端并输入:

php receive_logs_direct.php info warning error
# => [*] Waiting for logs. To exit press CTRL+C

以及,例如,你想发送一个error等级的日志消息,只需要输入:

php emit_log_direct.php error "Run. Run. Or it will explode."
# => [x] Sent 'error':'Run. Run. Or it will explode.'

(完整的(emit_log_direct.php源码)与(receive_logs_direct.php源码)在此)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981阅读 15,864评论 2 11
  • 来源 RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控...
    jiangmo阅读 10,343评论 2 34
  • 本文所有内容均个人从RabbitMQ官网教程中翻译,若图片文字的引用有任何侵权的地方,联系我,我会立马删除。 Th...
    JobinLi阅读 1,381评论 0 4
  • 已经快到中午了,楼下的公共区域灯光还亮着。"哎!这物业,这不是浪费能源"吗!老张一边愤愤不平地嘟嚷着,一边随手把灯...
    食之乐阅读 702评论 12 24