Just So So ...

今天,我的博客正式上线了,今天的主题是tp5框架,负载均衡后日志的统一管理(一个基于阿里日志的tp5日志驱动)

最近因为业务增长,导致单台服务器不够用,所有配置了负载均衡,虽然性能上得到了提升,但对于我们开发来说,找BUG,查日志就非常蛋疼了,要上多台服务器上看日志,为了解决日志的统一管理,基于阿里云的日志管理,我写了一个tp5的日志驱动。废话不多说,直接搞起。

  1. 阿里云日志php-sdk下载

  2. 代码部署
    1.将下载下来的代码改个名字改成aliyunlog(原来的名字太长了),统一丢入tp5第三方拓展目录(vendor)下。
    2.在thinkphplibrarythinklogdriver(这是tp5日志驱动目录)下新建文件,命名为Aliyun.php,写入如下代码:
  <?php
    namespace think\log\driver;
    use think\App;
    use think\Request;
    use think\Config;
    
    /**
     * 本地化调试输出到文件
     */
    class Aliyun
    {
        protected $config = [
            'endpoint' => 'cn-shanghai.log.aliyuncs.com', // 选择与上面步骤创建项目所属地域匹配的Endpoint
            'accessKeyId' => '******',        // 使用你的阿里云访问密钥AccessKeyId
            'accessKey' => '**********',             // 使用你的阿里云访问密钥AccessKeySecret
            'project' => 'ljlog-test',                  // 输入阿里云日志服务创建的项目名称
            'logstore' => 'ljlog-test'                // 输入阿里云日志服务创建的日志库名称
        ];
        // 实例化并传入参数
        public function __construct($config = [])
        {
            if (is_array($config)) {
                $this->config = array_merge($this->config, $config);
            }
        }
    
        /**
            * 日志写入接口
            * @access public
            * @param array $log 日志信息
            * @return bool
            */
        public function save(array $log = [])
        {
            $insert = [];
            $timestamp = time();
            $datetime = isset($this->config['time_format'])?date($this->config['time_format']):date("Y-m-d H:i:s");
    
            if (App::$debug) {
                if (isset($_SERVER['HTTP_HOST'])) {
                    $insert['current_url'] =  $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
                } else {
                    $insert['current_url'] = "cmd:" . implode(' ', $_SERVER['argv']);
                }
    
                $runtime    = round(microtime(true) - THINK_START_TIME, 10);
                $qps        = $runtime > 0 ? number_format(1 / $runtime, 2). 'req/s]' : '∞'. 'req/s]';
                $runtime_str=  number_format($runtime, 6) . 's';
                $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2);
                $file_load  = count(get_included_files());
                $server     = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '0.0.0.0';
                $remote     = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
                $method     = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
                $insert     = [
                    'timestamp'=>$timestamp,
                    'datetime'=>$datetime,
                    'method'=>$method,
                    'runtime'=>$runtime_str,
                    'qps'=>$qps,
                    'memory_use'=>$memory_use . 'kb',
                    'file_load'=>$file_load,
                    'server'=>$server,
                    'remote'=>$remote
                ];
            }
    
            $content=[];
            foreach ($log as $type => $val) {
                if (isset($content[$type])) {
                    $n = count($val);
                } else {
                    $n=0;
                }
                foreach ($val as $msg) {
                    if (!is_string($msg)) {
                        $msg = var_export($msg, true);
                    }
                    $insert[$type.'_'.$n]=$msg;
                    $n++;
                }
                // $content .= $type.$msg;
                // if (in_array($type, $this->config['apart_level'])) {
                //     $this->log(['log'=>$content]);
                // }
            }
            dump($insert);
            // $insert['log']=json_encode($content, 256);
          
            //\array_push($insert, $content);
            $this->log($insert);
            return true;
        }
    
        protected function log($insert=[])
        {
            vendor('aliyunlog.Log_Autoload');
            $client = new \Aliyun_Log_Client($this->config['endpoint'], $this->config['accessKeyId'], $this->config['accessKey']);
            #列出当前project下的所有日志库名称
            // $req1 = new \Aliyun_Log_Models_ListLogstoresRequest($project);
            // $res1 = $client->listLogstores($req1);
      
            $topic = "";
            $source = "";
            $logitems = array();
            
            $contents = $insert;
            dump($contents);
            $logItem = new \Aliyun_Log_Models_LogItem();
            $logItem->setTime(time());
            $logItem->setContents($contents);
            array_push($logitems, $logItem);
            
            $req2 = new \Aliyun_Log_Models_PutLogsRequest($this->config['project'], $this->config['logstore'], $topic, $source, $logitems);
            $res2 = $client->putLogs($req2);
        }
    }

3.修改tp5 默认的日志驱动,改为我们新写的日志驱动

打开tp5的config.php文件,找到

  'log'                    => [
        // 日志记录方式,内置 file socket 支持扩展
        'type'  => 'file',
       //'type'  => 'test',
        // 日志保存目录
        'path'  => LOG_PATH,
        // 日志记录级别
        'level' => [],
        //'apart_level'   =>  ['error','sql'],
    ],

改为

   'log'                    => [
    // 日志记录方式,内置 file socket 支持扩展
    'type'  => 'Aliyun',
   //'type'  => 'test',
    // 日志保存目录
    'path'  => LOG_PATH,
    // 日志记录级别
    'level' => [],
    //'apart_level'   =>  ['error','sql'],
],

至此,日志驱动就改好了,赶紧试试吧。
最后说说其它的解决方案,如果是刚开始搭建阿里云的负载均衡,所有的代码可以使用阿里云的文件系统nas,它可以挂载在多台服务服务器,就像云盘一样使用,可以让多台服务器共享代码,减少了繁杂的数据同步,就跟在一台服务器上一样。

发表评论

电子邮件地址不会被公开。 必填项已用*标注