Rabbit 学习总结(实现延迟队列)

参考资料
https://blog.csdn.net/demon3182/article/details/77482725

延时队列参考资料
https://blog.csdn.net/u012119576/article/details/74677835

如果你希望使用一个可靠性高、功能强大、易于管理的消息队列系统那么就选择RabbitMQ吧,如果你想用一个性能高,但偶尔丢点数据不是很在乎可以使用kafka或者zeroMQ

下面封装了一个类,实现了一个添加队列和一个消费队列:

<?php
/**
 * @note: 消息队列类
 * @author: wuLibo
 * createTime: 2018/8/10 14:32
 */


//引用所需文件
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;

/**
 * Class RabbitMQ
 */
class RabbitMQ {

    private $connection; //连接

    private $channel; //渠道

    private $logFileUrl = './log/';

    public function __construct($config)
    {
        try{
            $this->connection = new AMQPStreamConnection($config['host'], $config['port'], $config['user'], $config['password']);
            if(!$this->connection){
                throw new \Exception('连接失败');
            }
            $this->channel = $this->connection->channel();
        }catch (\Exception $e){
            $this->writeLog("file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()}");
        }
    }

    /**
     * @note:添加队列
     * @author: wulibo <13488215611@163.com>
     * @createTime: 2018/8/10 14:22
     * @param $data  数据
     * @param $callbackString  命名空间加函数名称用'::'隔开 命名空间必须和路由一致
     * @param $name  名称
     * @param $expiration  延迟时间 单位秒
     * @param string $prefix  前缀
     */
    public function pushMessage($data,$callbackString,$name,$expiration,$prefix = 'cache_'){
        try{
            $cache_exchange_name = $prefix.$name.'_'.$expiration;
            $cache_queue_name = $prefix.$name.'_'.$expiration;

            $this->channel->exchange_declare('delay_exchange', 'direct',false,false,false);
            $this->channel->exchange_declare($cache_exchange_name, 'direct',false,false,false);

            $tale = new AMQPTable();
            $tale->set('x-dead-letter-exchange', 'delay_exchange');
            $tale->set('x-dead-letter-routing-key','delay_exchange');
            $tale->set('x-message-ttl',$expiration*1000);
            $this->channel->queue_declare($cache_queue_name,false,true,false,false,false,$tale);
            $this->channel->queue_bind($cache_queue_name, $cache_exchange_name,'');

            $this->channel->queue_declare('delay_queue',false,true,false,false,false);
            $this->channel->queue_bind('delay_queue', 'delay_exchange','delay_exchange');
            $data['callback'] = $callbackString;
            $arr = http_build_query($data);

            $msg = new AMQPMessage($arr,array(
                'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,
            ));

            $this->channel->basic_publish($msg,$cache_exchange_name,'');
            echo date('Y-m-d H:i:s')." [x] Sent $arr || $expiration ".PHP_EOL;
        }catch (\Exception $e){
            echo "error(file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()})";
            $this->writeLog("file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()}");
        }
    }

    /**
     * @note:消费队列
     * @author: wulibo <13488215611@163.com>
     * @createTime: 2018/8/10 14:22
     */
    public function outMessage(){
        try{
            $this->channel->exchange_declare('delay_exchange', 'direct',false,false,false);
            $this->channel->exchange_declare('cache_exchange', 'direct',false,false,false);


            $this->channel->queue_declare('delay_queue',false,true,false,false,false);
            $this->channel->queue_bind('delay_queue', 'delay_exchange','delay_exchange');

            echo ' [*] Waiting for message. To exit press CTRL+C '.PHP_EOL;

            $callback = function ($msg){
                try{
                    parse_str($msg->body,$data);
                    $call = explode('::',$data['callback']);
                    if(!is_array($call)){
                        throw new \Exception('参数错误');
                    }
                    $file = str_replace('\\','/',$call[0]).'.php';
                    if(!file_exists($file)){
                        throw new \Exception('文件加载错误');
                    }
                    include_once $file;
                    $class = new $call[0];
                    $function = $call[1];
                    unset($data['callback']);
                    $class->$function($data);
                    echo date('Y-m-d H:i:s')." [x] Received",$msg->body,PHP_EOL;
                    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
                }catch (\Exception $e){
                    $this->writeLog("file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()}");
                }
            };
            //只有consumer已经处理并确认了上一条message时queue才分派新的message给它
            $this->channel->basic_qos(null, 1, null);
            $this->channel->basic_consume('delay_queue','',false,false,false,false,$callback);


            while (count($this->channel->callbacks)) {
                $this->channel->wait();
            }
        }catch (\Exception $e){
            echo "error(file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()})";
            $this->writeLog("file:{$e->getFile()};line:{$e->getLine()};message:{$e->getMessage()}");
        }
    }

    /**
     * @note:记录日志
     * @author: wulibo <13488215611@163.com>
     * @createTime: 2018/8/10 16:39
     * @param $data
     */
    public function writeLog($data){
        $years = date('Y-m');

        //设置路径目录信息
        $url = $this->logFileUrl.$years.'/'.date('Ymd').'_request_log.txt';
        $dir_name=dirname($url);
        //目录不存在就创建
        if(!file_exists($dir_name))
        {
            //iconv防止中文名乱码
            $res = mkdir(iconv("UTF-8", "GBK", $dir_name),0777,true);
        }
        $fp = fopen($url,"a");//打开文件资源通道 不存在则自动创建
        fwrite($fp,var_export($data,true)."\r\n");//写入文件
        fclose($fp);//关闭资源通道
    }

    public function __destruct()
    {
        $this->channel->close();
        $this->connection->close();
    }
}

下面是添加队列的代码:

require __DIR__.'/RabbitMQ.php'; 
$config = [ 'host'=>'127.0.0.1', 'port'=>5672, 'user'=>'guest', 'password'=>'guest' ]; 
$RabbitMQ = new RabbitMQ($config); $data['abc'] = 'abc'; 
$RabbitMQ->pushMessage($data,'test\\test::ccc','demo',1);die;

下面是消费队列代码:

require __DIR__.'/RabbitMQ.php'; 
$config = [ 'host'=>'127.0.0.1', 'port'=>5672, 'user'=>'guest', 'password'=>'guest' ];
$RabbitMQ = new RabbitMQ($config); 
$RabbitMQ->outMessage();die;

亲测通过,大神指教

转载于:https://my.oschina.net/u/3482593/blog/1925878

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值