RabbitMQ的PHP教程之topic (五)

学习完了RabbitMQ的PHP教程之Routing (四),route的核心思想就是告诉我们,queue是可以绑定多少routeKey,同时接收多个routeKey的消息,在文章的末尾,我也总结exchange、routeKey、queue、message之间的对应关系 。在文中有以下几行代码:

$queue->bind('exchange.log','warning');
$queue->bind('exchange.logs','error');
$queue->bind('exchange.logs','critical');
$queue->bind('exchange.logs','alert');
$queue->bind('exchange.logs','emergency');

我们搞PHP也知道,这种写法太过于死板。如果接收的消息routeKey很多,那我们就的一行行添加(当然你可以采用foreach循环),如果我们要对日志的来源进行再分类,比方说有register、login、mail等等,那么久需要bind很多的routeKey,大概会如下:

$queue->bind('exchange.log','register.warning');
$queue->bind('exchange.logs','register.error');
$queue->bind('exchange.logs','register.critical');
$queue->bind('exchange.logs','register.alert');
$queue->bind('exchange.logs','register.emergency');

.......

$queue->bind('exchange.log','mail.warning');
$queue->bind('exchange.logs','mail.error');
$queue->bind('exchange.logs','mail.critical');
$queue->bind('exchange.logs','mail.alert');
$queue->bind('exchange.logs','mail.emergency');

那么我们有没有一种办法来处理这种情况呢,这就是本章的学习的exchange中topic类型。 使用topic类型后,routKey支持模糊匹配,但仅支持以下2种写法:

*(星号)可以代表一个单词
#(井号)可以代表零个或多个单词 //请务必注意是单词,此时的routeKey是使用.链接的字符串。

我还是举例说明吧,假设我们有一个需求,需要对日志的来源进行分类处理。
不管是从register、login还是mail中,warning, error, critical, alert, emergency都转发到queue.log.error队列,notice都转发到queue.log.notice队列,debug、info都转发到queue.log.debug中。代码如下:

send.php

$channel = new \AMQPChannel($conn);
$channel->qos(0,0);

$exchange = new \AMQPExchange($channel);
$exchange->setName('exchange.all.logs');
$exchange->setType(AMQP_EX_TYPE_TOPIC);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();

//循环生成消息需要发布的消息
$origins = ['register','login','mail'];
$levels = ['debug','info','notice','warning','error','critical','alert','emergency'];
foreach ($origins as $origin) {
    foreach ($levels as $level) {
        $message = "[$origin]Message[$level]";
        $routeKey = "$origin.$level";
        //echo $message."======".$routeKey."\n";
        $result = $exchange->publish($message, $routeKey);
        var_dump($result);
    }
}

receive.php

$channel = new \AMQPChannel($conn);
$channel->qos(0,1);

$queue = new \AMQPQueue($channel);
$queue->setName("queue.all.errors");
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$queue->bind('exchange.all.logs','#.warning');
$queue->bind('exchange.all.logs','#.error');
$queue->bind('exchange.all.logs','#.critical');
$queue->bind('exchange.all.logs','#.alert');
$queue->bind('exchange.all.logs','#.emergency');
$queue->consume('processMessage',AMQP_AUTOACK);

function processMessage($envelope, $queue) {
    global $i;
    echo "Message $i: " . $envelope->getBody() . "\n";
    $i++;
}

一定要注意#*都表示的是单词,不是单个字母。

 相关阅读:

  1. RabbitMQ的原理与操作示例
  2. RabbitMQ AMQP 消息模型攻略
  3. PHP中的AMQP类
  4. RabbitMQ的PHP教程之入门 (一)
  5. RabbitMQ的PHP教程之工作队列 (二)
  6. RabbitMQ的PHP教程之发布/订阅(三)
  7. RabbitMQ的PHP教程之Routing (四)
  8. RabbitMQ的PHP教程之topic (五)
  9. RabbitMQ的PHP教程之RPC (六)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>