thinkphp5 Redis队列日志服务

之前业务上写日志记录的时候都是同步处理,日志处理模块总是要浪费一些时间的,导致系统整体响应较慢,上 kafka 那种级别的东西又有点杀鸡牛刀,于是打算上 Redis,利用 List 做一下队列,东西不难,记个思路。

前提:

1. 安装Redis  2. 安装 php_redis 扩展

思路:

代码:

\application\common\command\Log.php

<?php
// +----------------------------------------------------------------------
// | Author: Liu Xiaoyu <[email protected]>
// +----------------------------------------------------------------------
// | Date: 2019/10/15 8:16
// +----------------------------------------------------------------------
namespace app\common\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Exception;


class Log extends Command
{
    protected function configure()
    {
        $this -> setName('log:start') -> setDescription('Start Log Server By Redis');
    }

    protected function execute(Input $input, Output $output)
    {
        $redis = new \Redis();
        $redis -> connect('127.0.0.1', 6379);
        // 获取 数据库方法
        // 我这的目的 后边有个地方 要根据之前传的参数 找对应方法 扔到 redis里存一下, hash 读起来快
        if (!$redis -> hLen('coa_method')) {
            $method = db('method') -> field('name, en_name, method') -> select();
            $hash = [];
            foreach ($method as $v) {
                $hash[$v['method']] = serialize($v);
            }
            $redis -> hMSet('coa_method', $hash);
        }


        while (true) {
            try {
                // 取出队列头
                $task = $redis->lPop('coa_log');
                if(!$task) {
                    // 没有数据 睡3秒, 防止 不断循环 整死了
                    sleep(3);
                    continue;
                }
                $log = unserialize($task);
//                dump($log);
                // 这个地方是一个小逻辑
                for ($i = 0; $i < strlen($log['controller']); $i++) {
                    echo $log['controller'][$i];
                    if ( (ord($log['controller'][$i]) >= ord('A')) && (ord($log['controller'][$i]) <= ord('Z')) && $i !== 0) {
                        // 有大写字符, 插一下
                        $log['controller'] = substr_replace($log['controller'], '_',$i, 0);
                        $i++;
                    }
                }
                // 获取方法名所对中文
                $method_str = $log['module'].'/'.$log['controller'].'/'.$log['action'];
                $arr_str = [
                    'name' => '',
                    'en_name' => '',
                ];
                $method_str = strtolower($method_str);
                if ($redis -> hExists('coa_method', $method_str)) {
                    $hash_str = $redis -> hGet('coa_method', $method_str);
                    $arr_str = unserialize($hash_str);
                }

                $log['cn_name'] = $arr_str['name'];
                $log['en_name'] = $arr_str['en_name'];
                // save
                db('log') -> insert($log);

            } catch (\RedisException $exception) {
                echo $exception -> getMessage();
            }
        }
    }


}


在 \application\command.php 加入

return [
    'LogServer' => 'app\common\command\Log'
];

至此,轮询进程(消费者)已经写完,根目录下执行

php think LogServer

没有反应就对了,因为现在队列里是空的,sleep了,可以在 sleep 那里加上echo 看看 什么反应。

现在开始写 任务

\application\common\behavior\Log.php

<?php
namespace app\common\behavior;

use think\facade\Request;
class Log
{
    public function run(Request $request = null)
    {
        // 获取信息
        try {
            $userinfo = session('userinfo');
            $info = [
                'module' => Request::module(),
                'controller' => Request::controller(),
                'action' => Request::action(),
                'param' => serialize(Request::param()),
                'username' => $userinfo['username'],
                'userid' => $userinfo['id'],
                'is_admin' => $userinfo['is_admin'],
                'time' => time()
            ];

            // 加入 redis 队列
            $redis = new \Redis();
            $redis -> connect('127.0.0.1', 6379);
            // 完毕
            $redis -> rPush('coa_log', serialize($info));
        } catch (\RedisException $exception) {
            // echo $exception -> getMessage();
        }
    }
}

\application\tags.php 在 app_begin 这里加上

 // 应用开始
    'app_begin'    => [
        '\app\common\behavior\Log',
    ],

好了,前面开始跑业务吧,看看刚才 php think LogServer 的命令行是不是输出东西了,里面有一些业务逻辑,根据实际更改即可。

代码是在 Win下开发的,linux下同理。

发布了31 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/oZuoYu123/article/details/102587546