RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中

本章将介绍如何使用fanout模式将消息推送到多个队列。
有时我们会遇到这样的情况,多个功能模块都希望得到完整的消息数据。例如一个log的消息,一个我们希望输出在屏幕上实时监控,另外一个用户持久化日志。这时就可以使用fanout模式。fanout模式模式不像direct模式通过routingkey来进行匹配,而是会把消息发送到所以的已经绑定的队列中。

RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中_第1张图片

新建fanout.php用来发布消息。ca.php和cb.php用来订阅不同队列消费消息。

fanout.php

 '10.99.121.137', 'port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$connection->connect() or die("Cannot connect to the broker!\n");
try {
        $channel = new AMQPChannel($connection);
        $exchange = new AMQPExchange($channel);
        $exchange->setName($exchangeName);
        $exchange->setType(AMQP_EX_TYPE_FANOUT);
        $exchange->setFlags(AMQP_DURABLE);
        $exchange->declareExchange();

        for($i=0 ; $i<100;$i++){
        $exchange->publish($message.$i,"");

        var_dump("[x] Sent $message $i");
        }
} catch (AMQPConnectionException $e) {
        var_dump($e);
        exit();
}
 $connection->disconnect();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

ca.php

 '10.99.121.137','port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$connection->connect() or die("Cannot connect to the broker!\n");

$channel = new AMQPChannel($connection);

$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_FANOUT);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();

$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$queue->bind($exchangeName, $routeKey);

//阻塞模式接收消息
echo "Message:\n";
while(True){
    $queue->consume('processMessage');
    //$queue->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
}

$conn->disconnect();
/**
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $q) {
    $msg = $envelope->getBody();
    sleep(1);
    echo $msg."\n"; //处理消息
    $q->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

cb.php

/*
 * RabbitMQ fanout 模式
 * create by superrd
 */

$exchangeName = 'log';
$queueName = 'queueb';
$routeKey = '';

$connection = new AMQPConnection(array('host' => '10.99.121.137','port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$connection->connect() or die("Cannot connect to the broker!\n");

$channel = new AMQPChannel($connection);

$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_FANOUT);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();

$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$queue->bind($exchangeName, $routeKey);

//阻塞模式接收消息
echo "Message:\n";
while(True){
    $queue->consume('processMessage');
    //$queue->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
}

$conn->disconnect();
/**
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $q) {
    $msg = $envelope->getBody();
    sleep(1);
    echo $msg."\n"; //处理消息
    $q->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中_第2张图片

RabbitMQ消息队列-通过fanout模式将消息推送到多个Queue中_第3张图片

可以看到ca和cb收到的消息完全一致。注意以上代码fanout.php中并没有新建队列,所以先运行ca.php和cb.php的脚本,如果先运行fanout.php因为找不到绑定的队列数据就会丢失。
还有一种情况我们有可能随时增加一项处理机制,如果在声明queue时不指定名字,那么RabbitMQ会随机为我们生成一个名字,如果不指定queue为持久化队列那在消息为空并且订阅者为0时自动删除该队列。这样Queue挥之即来呼之即去。


 '10.99.121.137','port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$connection->connect() or die("Cannot connect to the broker!\n");

$channel = new AMQPChannel($connection);

$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_FANOUT);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();

$queue = new AMQPQueue($channel);
$queue->declareQueue();
$queue->bind($exchangeName, $routeKey);

//阻塞模式接收消息
echo "Message:\n";
while(True){
    $queue->consume('processMessage');
    //$queue->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
}

$conn->disconnect();
/**
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $q) {
    $msg = $envelope->getBody();
    sleep(1);
    echo $msg."\n"; //处理消息
    $q->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}

你可能感兴趣的:(mq)