安装rabbit-mq,php联调rabbit-mq

  1. 安装rabbit
    1. brew install rabbit
  2. 启动停止rabbit
    1. 启动    /usr/local/Cellar/rabbitmq/3.9.3/sbin/rabbitmqctl start_app
    2. 停止  /usr/local/Cellar/rabbitmq/3.9.3/sbin/rabbitmqctl stop_app
    3. 重置    /usr/local/Cellar/rabbitmq/3.9.3/sbin/rabbitmqctl reset
  3. 交换机类型
    1. Direct Exchange
      1. Direct直连交换机:
      2. 直连交换机是一种带路由功能的交互机,一个队列通过routing_key与一个交换机绑定,当消息被发送的时候,需要指定一个routing_key,这个消息被送达交换机的时候,就会被交换机送到指定的队列里面去。同样一个routing_key也是支持应用到多个队列中的,当一个交换机绑定多个队列时,消息就会被送到对应的队列去处理。
      3.  适用场景:有优先级的任务,根据任务的优先级把消息发送到对应的队列,这样可以指派更多的资源去处理高优先级的队列。
    2. Fanout Exchange
      1. 扇形交换机,转发消息到所有绑定队列(速度最快)
      2. 扇形交换机是最基本的交换机类型,它做的事情很简单--广播信息。Fanout交换机会把接收到的消息全部转发到绑定的队列上。因为广播不需要“思考”,所以Fanout交换机是四种交换机中速度最快的。
      3. 适用场景:需要随时增加减少业务处理的队列,例如注册、下单等功能需要增加送积分功能,只需要增加一个绑定到交换机的队列去处理新业务,无需修改旧的业务逻辑,从而达到业务解耦,非常容易扩展。
    3. Topic Exchange
      1. Topic主题交换机:
      2. 直连交换机的routing_key方案非常简单,如果我们希望一条消息发送给多个队列,那么这个交换机需要绑定上非常多的routing_key,假设每个交换机上都绑定一堆的routing_key连接到各个队列上。那么消息队列的管理就会异常的困难。
      3. 所以RabbitMQ提供了一种主题交换机,发送到主题交换机上的消息需要携带指定规则的routing_key,主题交换机会根据这个规则将数据发送到对应的(多个)队列上。
      4. 主题交换机的routing_key需要有一定的规则,交换机和队列的binding_key需要采用*.#.*.....的格式,每个部分用.分开,其中:*表示一个单词#表示任意数量(零个或多个)单词。
      5. 适用场景:消息需要基于多重条件进行路由到达对应队列,例如:日志系统,不仅可以根据日志的级别而且能根据日志的来源进行订阅。
    4. Headers Exchanges
      1. header exchange(头交换机)和主题交换机有点相似,但是不同于主题交换机的路由是基于路由键,头交换机的路由值基于消息的header数据。
      2. 主题交换机路由键只有是字符串,而头交换机可以是整型和哈希值

 示例:

  composer.json(composer加载php-amqplib库)

{
    "require": {
        "php-amqplib/php-amqplib": ">=2.6.1"
    }
}

  rabbit-mq.config.php(rabbitMQ配置文件)

<?php
return [
    'rabbitmq' => [
        'host' => '127.0.0.1',
        'port' => '5672',
        'login' => 'guest',
        'password' => 'guest',
        'vhost' => '/'
    ]
];
?>

  

  RabbitMQ.php(封装rabbitMQ)

<?php

    require_once dirname(dirname(__FILE__)).'/vendor/autoload.php';
    use PhpAmqpLib\Connection\AMQPStreamConnection;
    use PhpAmqpLib\Message\AMQPMessage;
    use PhpAmqpLib\Wire\AMQPTable;
    use PhpAmqpLib\Exchange\AMQPExchangeType;


    class RabbitMQ
    {

        private $host;
        private $port;
        private $user;
        private $password;
        protected $connection;
        protected $channel;


        /**
         * RabbitMQ constructor.
         */
        public function __construct()
        {
            $config = require dirname(dirname(__FILE__))."/model/rabbit-mq.config.php";
            $this->host = $config['rabbitmq']['host'];
            $this->port = $config['rabbitmq']['port'];
            $this->user = $config['rabbitmq']['login'];
            $this->password = $config['rabbitmq']['password'];
            $this->connection = new AMQPStreamConnection($this->host, $this->port, $this->user, $this->password);
            $this->channel    = $this->connection->channel();
        }

        /**
         * 创建交换机
         */
        public function createExchange($exchangeName, $channelType){
            $this->channel->exchange_declare($exchangeName, $channelType, false, false, false);
        }

        /**
         * 绑定交换机
         */
        public function bindQueue($queueName,$exchangeName, $severity){
            $this->channel->queue_bind($queueName, $exchangeName,$severity);
        }



        /*创建队列
         * queue   队列名称
         * durable    是否持久化。true持久化,队列会保存磁盘。服务器重启时可以保证不丢失相关信息   已创建的队列,不在支持修改该参数
         * exclusive    设置是否排他。true排他的。如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。
                        排它是基于连接可见的,同一个连接不同信道是可以访问同一连接创建的排它队列,
                        “首次”是指如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列,即使这个队列是持久化的,
                        一旦连接关闭或者客户端退出,该排它队列会被自动删除,这种队列适用于一个客户端同时发送与接口消息的场景。
         * autoDelete   设置是否自动删除。true是自动删除。自动删除的前提是:致少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,
                        才会自动删除生产者创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列

         * */
        public function createQueue($queueName, $passive = false,$durable = false,$exclusive = false,$autoDelete = false,$nowait = false,$args = []){
            $this->channel->queue_declare($queueName, $passive, $durable, $exclusive, $autoDelete, $nowait, $args);
        }

        /**
         * 生成信息
         * @param $message
         */
        public function sendMessage($message, $routeKey='', $exchange = '', $properties = [])
        {
            $data = new AMQPMessage(
                $message, $properties
            );
            $this->channel->basic_publish($data, $exchange, $routeKey);
        }

        /**
         * 创建延时队列
         * @param $ttl
         * @param $delayExName
         * @param $delayQueueName
         * @param $queueName
         */
        public function createDelayQueue($ttl, $delayExName, $delayQueueName, $queueName)
        {
            $args = new AMQPTable([
                'x-dead-letter-exchange'    => $delayExName,
                'x-message-ttl'             => $ttl, //消息存活时间
                'x-dead-letter-routing-key' => $queueName
            ]);
            $this->channel->queue_declare($queueName, false, true, false, false, false, $args);
            //绑定死信queue
            $this->channel->exchange_declare($delayExName, AMQPExchangeType::DIRECT, false, true, false);
            $this->channel->queue_declare($delayQueueName, false, true, false, false);
            $this->channel->queue_bind($delayQueueName, $delayExName, $queueName, false);
        }

        /**
         * 消费消息
         * @param $queueName
         * @param $callback
         * @throws \ErrorException
         */
        public function consumeMessage($queueName,$callback)
        {
            /*
             * 创建队列
             * queue            队列名
             * consumer_tag     消费者标签
             * no_local         这个功能属于AMQP的标准,但是rabbitMQ并没有做实现.
             * no_ack           收到消息后,是否不需要回复确认即被认为被消费
             * exclusive        排他消费者,即这个队列只能由一个消费者消费.适用于任务不允许进行并发处理的情况下.比如系统对接
             * nowait           不返回执行结果,但是如果排他开启的话,则必须需要等待结果的,如果两个一起开就会报错
             * callback         回调函数
             * */
            $this->channel->basic_consume($queueName, '', false, false, false, false, $callback);
            while ($this->channel->is_consuming()) {
                $this->channel->wait();
            }
        }

        /**
         * @throws \Exception
         */
        public function __destruct()
        {
            $this->channel->close();
            $this->connection->close();
        }
    }

  producer.php(生产者)

<?php
    require_once './vendor/autoload.php';
    include('./model/RabbitMQ.php');

    $data = implode(' ', array_slice($argv, 1));
    $num = implode(' ', array_slice($argv, 2));
    $severity = implode(' ', array_slice($argv, 3));

    $exchangeName = 'direct_logs1';
    $channelType = 'direct';
    $queueName = 'direct_queue1';

//    $ttl            = 1000 * 10;//10s后超时
//    $delayExName    = 'delay-order-exchange';//超时exchange
//    $delayQueueName = 'delay-order-queue';//超时queue
//    $queueName      = 'ttl-order-queue';//订单queue

    $rabbitObj = new RabbitMQ();
    $rabbitObj->createExchange($exchangeName,$channelType);
    $rabbitObj->createQueue($queueName,false,true);
    //$rabbitObj->createDelayQueue($ttl,$delayExName,$delayQueueName,$queueName);

    for($i = 1;$i <= $num;$i++){
        $properties = ['delivery_mode' => 2];
        $rabbitObj->sendMessage($i.'-'.$data,$severity,$exchangeName,$properties);
        //$rabbitObj->sendMessage($i.'-'.$data,$queueName);
        echo " [x] Sent ".$i.'-'.$data.'-'.$severity."\n";
    }

  consume.php(消费者)

<?php
    require_once './vendor/autoload.php';
    include('./model/RabbitMQ.php');

    $severity = implode(' ', array_slice($argv, 1));

    $exchangeName = 'direct_logs1';
    $channelType = 'direct';
    $queueName = 'direct_queue1';
    $callBack = function($msg) {
        echo " [x] Received ", $msg->body, "\n"; //根据"."数量个数获取延迟时间,单位秒
        //sleep(2);  //模拟业务执行时间延迟
        echo " [x] Done", "\n";
        $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
    };

    $rabbitObj = new RabbitMQ();
    $rabbitObj->createExchange($exchangeName,$channelType);
    $rabbitObj->createQueue($queueName,false,true);
    $rabbitObj->bindQueue($queueName,$exchangeName,$severity);

    $rabbitObj->consumeMessage($queueName,$callBack);

  

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小斌0810

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值