Topic Exchange
此模式下交换机,在推送消息时, 会根据消息的主题词和队列的主题词决定将消息推送到哪个队列. 交换机只会为 Queue 分发符合其指定的主题的消息。
- 向交换机发送消息时,消息的 routing key 就是主题关键词,主题词不能随意设置,必须由 "." 联结多个主题词 (如:log.error、log.warn) .
- 必须将队列显示的绑定到指定的交换机上.
- 为队列指定队列主题词时,可以使用通配符: "#": 表示 0 或多个主题词; "*": 表示 1 个主题词.
示例
producer.php
header('Content-Type: text/html; charset=utf-8'); // 连接设置 $conConfig = [ 'host' => '127.0.0.1', 'port' => 5672, 'login' => 'root', 'password' => 'root', 'vhost' => '/' ]; try { // RabbitMQ 连接实例 $con = new AMQPConnection($conConfig); // 发起连接 $con->connect(); // 判断连接结果,true成功,false失败 if(!$con->isConnected()) { echo '连接失败';die; } // 新建通道 $channel = new AMQPChannel($con); // 在指定通道上新建交换机,如果新建的交换机与已存在交换机重名但属性不同,会产生406错误。如果新建交换机与已存在交换机完全相同,不会有任何影响 $exchange = new AMQPExchange($channel); // 交换机名称 $exchange->setName('test.topic'); // 交换机类型:按主题分发消息 $exchange->setType('topic'); // 声明交换机 $exchange->declareExchange(); // 发送消息到交换机,通过routing key指定消息的主题词 $state = $exchange->publish('apple', 'fruit.red'); if($state) echo 'Success' . PHP_EOL; else echo 'Fail' . PHP_EOL; $state = $exchange->publish('cat', 'animal.red'); if($state) echo 'Success' . PHP_EOL; else echo 'Fail' . PHP_EOL; $con->disconnect(); } catch(Exception $e) { echo $e->getMessage(); }
consumer.php
header('Content-Type: text/html; charset=utf-8'); // 连接设置 $conConfig = [ 'host' => '127.0.0.1', 'port' => 5672, 'login' => 'root', 'password' => 'root', 'vhost' => '/' ]; try { $connect = new AMQPConnection($conConfig); $connect->connect(); if(!$connect->isConnected()) { echo '连接失败';die; } $channel = new AMQPChannel($connect); $exchange = new AMQPExchange($channel); $exchange->setName('test.topic'); $exchange->setType('topic'); $exchange->declareExchange(); // 创建两个队列, 一个关联red主题词, 一个关联animal主题词 $queueRed = new AMQPQueue($channel); $queueAnimal = new AMQPQueue($channel); // 队列名称 $queueRed->setName('red.queue'); $queueAnimal->setName('animal.queue'); // 声明队列 $queueRed->declareQueue(); $queueAnimal->declareQueue(); // 为队列绑定主题词, *: 匹配0或多个任意主题词, #: 1个任意主题词. 绑定主题词时, 主题词出现的位置也要匹配 $queueRed->bind('test.topic', "*.red"); $queueAnimal->bind('test.topic', 'animal.#'); echo 'red queue: ' . PHP_EOL; while($msgEnvelope = $queueRed->get(AMQP_AUTOACK)) { $msg = $msgEnvelope->getBody(); echo $msg . PHP_EOL; } echo 'animal queue: ' . PHP_EOL; while($msgEnvelope = $queueAnimal->get(AMQP_AUTOACK)) { $msg = $msgEnvelope->getBody(); echo $msg . PHP_EOL; } $connect->disconnect(); }catch(Exception $e) { echo $e->getMessage(); }
运行结果:
red queue 获得了所有包含 red 主题词的消息, animal queue 仅获得包含 animal 主题的消息.
Fanout Exchange
该模式下的交换机是广播模式, 交换机会向所有绑定的队列分发消息, 不需要设置交换机和队列的 routing key. 即使设置了, 也会被忽略.
示例
producer.php
1 header('Content-Type: text/html; charset=utf-8'); 2 // 连接设置 3 $conConfig = [ 4 'host' => '127.0.0.1', 5 'port' => 5672, 6 'login' => 'root', 7 'password' => 'root', 8 'vhost' => '/' 9 ]; 10 11 try 12 { 13 // RabbitMQ 连接实例 14 $con = new AMQPConnection($conConfig); 15 // 发起连接 16 $con->connect(); 17 // 判断连接结果,true成功,false失败 18 if(!$con->isConnected()) 19 { 20 echo '连接失败';die; 21 } 22 // 新建通道 23 $channel = new AMQPChannel($con); 24 // 在指定通道上新建交换机,如果新建的交换机与已存在交换机重名但属性不同,会产生406错误。如果新建交换机与已存在交换机完全相同,不会有任何影响 25 $exchange = new AMQPExchange($channel); 26 // 交换机名称 27 $exchange->setName('test.fanout'); 28 // 交换机类型:广播模式 29 $exchange->setType('fanout'); 30 // 声明交换机 31 $exchange->declareExchange(); 32 33 for($i = 0; $i < 3; $i++) 34 { 35 $msg = '消息'; 36 // 发送消息到交换机,Fanout模式下不需要指定routing key。即使指定也会被忽略 37 $state = $exchange->publish($msg . $i); 38 if($state) 39 { 40 echo 'Success' . PHP_EOL; 41 }else 42 { 43 echo 'Fail' . PHP_EOL; 44 } 45 } 46 47 $con->disconnect(); 48 } 49 catch(Exception $e) 50 { 51 echo $e->getMessage(); 52 }
consumer.php
1 header('Content-Type: text/html; charset=utf-8'); 2 // 连接设置 3 $conConfig = [ 4 'host' => '127.0.0.1', 5 'port' => 5672, 6 'login' => 'root', 7 'password' => 'root', 8 'vhost' => '/' 9 ]; 10 11 try 12 { 13 $connect = new AMQPConnection($conConfig); 14 $connect->connect(); 15 if(!$connect->isConnected()) 16 { 17 echo '连接失败';die; 18 } 19 20 $channel = new AMQPChannel($connect); 21 22 $exchange = new AMQPExchange($channel); 23 $exchange->setName('test.fanout'); 24 $exchange->setType('fanout'); 25 $exchange->declareExchange(); 26 27 // 创建队列 28 $queue1 = new AMQPQueue($channel); 29 $queue2 = new AMQPQueue($channel); 30 31 // 队列名称 32 $queue1->setName('queue1'); 33 $queue2->setName('queue2'); 34 // 声明队列 35 $queue1->declareQueue(); 36 $queue2->declareQueue(); 37 // 绑定队列到交换机。Fanout模式下不需要指定routing key,即使指定也会被忽略 38 $queue1->bind('test.fanout'); 39 echo '队列1: ' . PHP_EOL; 40 while($msgEnvelope = $queue1->get(AMQP_AUTOACK)) 41 { 42 $msg = $msgEnvelope->getBody(); 43 echo $msg . PHP_EOL; 44 } 45 46 47 echo PHP_EOL . '队列2: ' . PHP_EOL; 48 $queue2->bind('test.fanout'); 49 while($msgEnvelope = $queue2->get(AMQP_AUTOACK)) 50 { 51 $msg = $msgEnvelope->getBody(); 52 echo $msg . PHP_EOL; 53 } 54 $connect->disconnect(); 55 }catch(Exception $e) 56 { 57 echo $e->getMessage(); 58 }
运行结果:
两个队列获得相同的消息.