RabbitMQ 在 PHP 下的简单使用 (二) -- Topic Exchange 和 Fanout Exchange

Topic Exchange

此模式下交换机,在推送消息时, 会根据消息的主题词和队列的主题词决定将消息推送到哪个队列. 交换机只会为 Queue 分发符合其指定的主题的消息。

  1. 向交换机发送消息时,消息的 routing key 就是主题关键词,主题词不能随意设置,必须由 "." 联结多个主题词 (如:log.error、log.warn) .
  2. 必须将队列显示的绑定到指定的交换机上.
  3. 为队列指定队列主题词时,可以使用通配符: "#": 表示 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 }

运行结果:

两个队列获得相同的消息.

猜你喜欢

转载自www.cnblogs.com/fxyy/p/10542026.html