rabbitmq php 代码示例

交换机类型

direct : 直连交换机, 根据路由键投递到与绑定键匹配的队列。
fanout : 扇形交换机,采用广播模式,投递到所有与之绑定的队列。
topic  : 主题交换机,对路由键与绑定键进行模式匹配后再投递到相应的队列。
headers : 头交换机,不处理路由键, 而是根据发送的消息内容中的 headers 属性进行匹配。


路由键与绑定键
routing_key : 发布消息时用的到 key 叫路由键, 它是一个精确的字符串
binding_key : 队列绑定到交换机时用到的 key 叫绑定键, 当交换机类型为 topic 时,绑定键可以包含通配符( * : 通配一个单词, # : 通配多个单词)。

 

docker 容器

docker run -–name mq  -e RABBITMQ_DEFAULT_USER=test -e RABBITMQ_DEFAULT_PASS=12345  -p 15672:15672 -p 5672:5672 -d rabbitmq

docker exec -it mq /bin/bash

# 启用管理插件
rabbitmq-plugins enable rabbitmq_management

# 管理界面 channels 标签无法点击
echo management_agent.disable_metrics_collector = false > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf

 

浏览器访问 localhost:15672 输入 test 12345  登录, 自己尝试创建交换机和队列,能更理解, 特别是代码里一笔带过的 Arguments 参数

 

测试 topic  交换机

<?php

$connect = new AMQPConnection(['login'=>'test', 'password'=>12345]); //创建连接
$connect->connect();

if(!$connect->isConnected()){
    exit("连接失败");
}

$channel  = new AMQPChannel($connect); //创建频道
$exchange = new AMQPExchange($channel); //创建交换机
$queue    = new AMQPQueue($channel); //创建队列

// 配置交换机
$exchange->setName('zbs.topic');
$exchange->setType(AMQP_EX_TYPE_TOPIC); //交换机类型 AMQP_EX_TYPE_DIRECT,AMQP_EX_TYPE_FANOUT,AMQP_EX_TYPE_HEADERS
$exchange->setFlags(AMQP_DURABLE);// 设置标志: AMQP_DURABLE 持久化, AMQP_PASSIVE 不创建,但不存在时抛出异常
$exchange->declareExchange();// 发布交换机,不存在时,自动创建

// 配置队列
$queue->setName('zbs.queue');
$queue->setFlags(AMQP_DURABLE); //设置标志: AMQP_DURABLE 持久化, AMQP_PASSIVE 不创建,但不存在时抛出异常, AMQP_EXCLUSIVE 独占队列, AMQP_AUTODELETE 没有监听时自动删除
$queue->declareQueue(); //发布队列,不存在时,自动创建.注意:发布队列后才能绑定到交换机
$queue->bind($exchange->getName(), 'news.*.*'); // 绑定键可以用通配符


// 发布消息, 通过交换机来发布消息
for($i = 0; $i < 10; $i++) {
    $exchange->publish("message{$i}", 'news.sport.china', AMQP_MANDATORY); // AMQP_MANDATORY 消息投递失败将报错误  AMQP_IMMEDIATE 消息应该立即被处理,高优先级
}

// 消费消息, 通过队列来消费消息
$queue->consume(function(AMQPEnvelope $message, AMQPQueue $queue){

    $queue->ack($message->getDeliveryTag()); // 消息确认

    echo $message->getBody() . "\n";

    // dump(
    //     $message->getExchangeName(),
    //     $message->getBody(),
    //     $message->getConsumerTag(),
    //     $queue->getConsumerTag(),
    //     $queue->getName(),
    //     $message->getConsumerTag() == $queue->getConsumerTag() ? 'valid' : 'not valid'
    // );

    sleep(1);

});

 

测试 headers 交换机

$connect = new AMQPConnection(['login'=>'test', 'password'=>12345]); //创建连接
$connect->connect();

if(!$connect->isConnected()){
    exit("连接失败");
}

$channel  = new AMQPChannel($connect); //创建频道

$exchange = new AMQPExchange($channel);
$exchange->setName('zbs.headers' );
$exchange->setType(AMQP_EX_TYPE_HEADERS);
$exchange->declareExchange();

$queue = new AMQPQueue($channel);
$queue->setName("zbs.headers");
$queue->declareQueue();

$arguments = array('x-match' => 'any', 'type' =>'custom', 'name'=>'tom'); // x-match: all 所有匹配, any 任意匹配
$queue->bind($exchange->getName(), null, $arguments);

// 发布消息
for($i = 0; $i < 10; $i++) {
    // 发布消息时 headers 头要匹配才能正确投递到队列
    $exchange->publish("headers message{$i}", null, AMQP_MANDATORY, ['headers'=> ['name' => 'tom' ]]);
}


// 消费消息, 为了表示消费功能在其他项目,这里我们重新创建对象
$queue = new AMQPQueue($channel);
$queue->setName("zbs.headers");
$queue->declareQueue();
$queue->consume(function(AMQPEnvelope $message, AMQPQueue $queue){

    $queue->ack($message->getDeliveryTag());
    echo $message->getBody() . "\n";
    sleep(1);


});

 

 总结一下:

1. 交换机和队列是多对多的关系

2. 交换机和队列之间的绑定键也可以有多个.

3. 创建,生产消息 和消费消息,其实是三个过程,如果已经明确知道交换机和队列的存在,那么你在生产消息时,只要声明交换机,而在消费消息时只需声明队列.

 

posted @ 2023-07-13 11:18  心随所遇  阅读(60)  评论(0编辑  收藏  举报