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

本文所有内容均个人从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
在上一个教程我们升级了我们的日志系统。与仅仅能够进行虚拟广播的fanout类型交换机不同,我们使用了一个direct类型交换机,并获得了可以选择性地接收日志的能力。

尽管使用direct交换机提升我们的系统,但它仍然是由限制的——它不能够在多个标准下进行路由。

在我们的日志系统中,我们可能希望不仅仅是根据日志等级来订阅日志,也可以根据发送日志的源。你可能已经从可以同时根据日志的严重性(info/warn/crit....)与设施(auth/cron/kern...)来路由日志的Unixsyslog工具知道这一概念。

这会带给我们非常多的灵活性——我们可能打算仅仅监听来自cron的严重错误日志而又监听来自kern的所有日志。

为了在我们的日志系统实现这一公功能,我们需要学习一个更加复杂的topic交换机

Topic交换机

消息发送到一个topic交换机不能随意设置routing_key——它必须是一系列以点分隔的词。这些词可以是随意的,但它们通常指定了消息的一些特性。有一些有效的路由键(routing key)的例子:'stock.usd.nyse'nyse.vmwquick.orange.rabbit。他们可以由很多你喜欢的路由键组成,最多不能超过255个字节(bytes)

绑定键(binding key)也必须是同样的格式。topic交换机的逻辑与direct交换机是相似的——一条携带特定路由键(routing key)发送的消息将会被分发到所有以与之匹配的绑定键(binding key)绑定的Queue(队列)。然而,关于绑定键,有两个需要特别注意的情况:

  1. *(星号)可以代替(任意)一个词。
  2. (井号)可以代替零个或者更多的词

这是一个最简单的解释例子:


topic exhange model

在这一个例子中,我们准备发送一些描述动物的消息。这些消息被发送时将会带有由三个单词组成(两个点)的路由键(routing key)。路由键(routing key)的第一个词将会描述速度,第二个描述颜色,第三个描述物种:'<speed>.<colour>.<species>'

我们创建了三个绑定:Q1队列以'*.orange.*路由键绑定,Q2'*.*.rabbitlazy.#(两个路由键)绑定。

这些绑定可以概括为:
Q1对所有orange(橙色)的动物感兴趣。
Q2想监听rabbit(兔子)的所有消息与lazy(慢吞吞的)动物的所有消息。

一条路由键(routing key)被设置为'quick.orange.rabbit的消息将会被交付到这两个队列。路由键为'lazy.orange.elephant'的消息也会被交付到这两个队列。而另一种路由键为'quick.orange.fox'的消息只会去到第一个(Q1)队列,以及'lazy.brown.fox'只会发送到第二个(Q2)队列。路由键为lazy.pink.rabbit的消息只会被发送到第二个(Q2)队列一次,尽管它符合两个绑定。'quick.brown.fox'不匹配任何一个绑定,所以它会被丢弃。

如果我们打破我们的规定,发送了一条只带有一个词或者带有四个词的路由键的消息,例如'orange'或者'quick.orange.male.rabbit',会发生什么呢?这些消息将不会匹配到任何绑定上并且将会被丢失。

在另一方面,尽管'lazy.orange.male.rabbit'拥有四个词,它将会匹配最后一个绑定lazy.#,并将会发送到第二个队列。


话题交换机(Topic Exchange)

话题交换机是十分强大的,同时它能表现得想其他的交换机一样。
当一个Queue(队列)"#"(井号)绑定键(binding key)绑定——它将会忽视路由键(routing key)去接收所有消息就像是一个fanout类型的交换机一样。

当特殊字符"*"(星号)"#"(井号)没有被用在绑定(键)上,这时候topic交换机由表现得像direct交换机一样。


把他们一起运行

我们准备在我们的日志系统中使用一个topic交换机。我们将从一个工作假设开始,即日志的路由键将有两个单词:"<facility>.<severity>"

代码与上一个教程的十分相似,

emit_log_topic.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();

// 声明一个topic交换机
$channel->exchange_declare('topic_logs', 'topic', false, false, false);

// 从命令行获取路由键
$routing_key = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'anonymous.info';
$data = implode(' ', array_slice($argv, 2));
if(empty($data)) $data = "Hello World!";

$msg = new AMQPMessage($data);

// 携带路由键发送到topic_logs交换机
$channel->basic_publish($msg, 'topic_logs', $routing_key);

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

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

receive_logs_topic.php的代码如下:

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

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

// 声明topic交换机
$channel->exchange_declare('topic_logs', 'topic', false, false, false);

// 获取非持久化队列
list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);

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

// 绑定多个绑定键到队列
foreach($binding_keys as $binding_key) {
    $channel->queue_bind($queue_name, 'topic_logs', $binding_key);
}

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();
?>

如果想接收所有日志:

php receive_logs_topic.php "#"

接收"kern"设备的所有日志:

php receive_logs_topice.php "kern.*"

或者你只想监听"critical"的日志:

php receive_logs_topic.php "*.critical"

你可以创建多个绑定:

php receive_logs_topic.php "kern.*" "*.critical"

以及,发送一个带有"kern.critical"路由键的日志请输入:

php emit_log_topic.php "kern.critical" "A critical kernel error"

用这些程序愉快地玩耍吧。要主意的是,这些代码是没有对路由或绑定键做任何的假设,你可能希望使用两个两个以上的路由键参数。

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

推荐阅读更多精彩内容