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下同理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章