此模式下,消息的routing key 和队列的 routing key 会被完全忽略,而是在交换机推送消息和队列绑定交换机时, 分别为消息和队列设置 headers 属性, 通过匹配消息和队列的 header 决定消息的分发.
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.headers'); // 交换机类型:按headers分发 $exchange->setType('headers'); // 声明交换机 $exchange->declareExchange(); // 设定消息的headers信息 $arguments = array( 'headers'=>array( 'type' => 'fruit', 'color' => 'red' ) ); // 发送消息到交换机,即使设置routing key也会被忽略 $state = $exchange->publish('消息1', 'test.rt', AMQP_NOPARAM, $arguments); if($state) echo 'Success' . PHP_EOL; else echo 'Fail' . PHP_EOL; // 设定headers信息 $arguments = array( 'headers'=>array( 'type' => 'animal', 'color' => 'red' ) ); $state = $exchange->publish('消息2', 'test.rt', AMQP_NOPARAM, $arguments); 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.headers'); $exchange->setType('headers'); $exchange->declareExchange(); // 创建队列 $queue1 = new AMQPQueue($channel); $queue2 = new AMQPQueue($channel); // 队列名称 $queue1->setName('header.queue1'); $queue2->setName('header.queue2'); $queue1->declareQueue(); $queue2->declareQueue(); // 设定队列的headers信息,x-match:all:全匹配,消息的headers信息与队列的必须完全匹配,any:消息的headers消息与队列的任意一项匹配即可 $headers1 = array( 'x-match'=>'all', 'type'=>'fruit', 'color'=>'red' ); $headers2 = array( 'x-match'=>'any', 'type'=>'animal', 'color'=>'red' ); // 绑定队列到交换机, 任意设置routing key $queue1->bind($exchange->getName(), 'queue1', $headers1); $queue2->bind($exchange->getName(), 'queue2', $headers2); echo '队列1: ' . PHP_EOL; while($msgEnvelope = $queue1->get(AMQP_AUTOACK)) { $msg = $msgEnvelope->getBody(); echo $msg . PHP_EOL; } echo PHP_EOL . '队列2: ' . PHP_EOL; while($msgEnvelope = $queue2->get(AMQP_AUTOACK)) { $msg = $msgEnvelope->getBody(); echo $msg . PHP_EOL; } $connect->disconnect(); }catch(Exception $e) { echo $e->getMessage(); }
运行 producer.php 推送消息, 然后运行 comsumer.php 结果如下:
队列1 要求 headers 完全匹配, 所以只接受到一条消息. 队列2 要求任意匹配即可, 所以接收到两条消息.