Swoole-日志落盘处理

1.ws.php

<?php
/**
 * Created by bingxiong.
 * Date: 5/19/18
 * Time: 7:43 PM
 * Description:
 */
class Ws{
    CONST HOST="0.0.0.0";
    CONST PORT=8811;
//    public $ws = null;
    CONST CHART_PORT =8812;

    public function __construct()
    {
//        重启的时候要获取sMembers获取看看key有没有值,有的话要删掉
        $this->ws = new swoole_websocket_server(self::HOST,self::PORT);
        $this->ws->listen(self::HOST,self::CHART_PORT,SWOOLE_SOCK_TCP);
        $this->ws->set([
            'enable_static_handler' => true, //
            'document_root' => "/Users/bingxiong/swoole/hdtocs/thinkphp/public/static",
            'worker_num' => 4,
            'task_worker_num' => 4,
        ]);
        $this->ws->on("workerstart",[$this,'onWorkerStart']);
        $this->ws->on("request",[$this,'onRequest']);
        $this->ws->on("open",[$this,'onOpen']);
        $this->ws->on("message",[$this,'onMessage']);
        $this->ws->on("task",[$this,'onTask']);
        $this->ws->on("finish",[$this,'onFinish']);
        $this->ws->on("close",[$this,'onClose']);
        $this->ws->start();
    }

    /**
     * onWorkerStart的回调
     * 加载框架文件
     * @param $server
     * @param $worker_id
     */
    public function onWorkerStart($server, $worker_id){
        // 定义应用目录
        define('APP_PATH', __DIR__ . '/../../../application/');
        // 加载框架引导文件
        require __DIR__ . '/../../../thinkphp/start.php';
    }

    /**
     * request的回调
     * @param $request
     * @param $response
     */
    public function onRequest($request,$response){
//        print_r($request->server);
//        把图标状态设置成404,防止日志中输出
        if($request -> server['request_uri'] == '/favicon.ico'){
            $response->status(404);
            $response->end();
            return;
        }

        //    将swoole中一些特别的用法装换成原生的php
        $_SERVER =[];
        if(isset($request->server)){
            foreach ($request->server as $k => $v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }

        $_GET = [];
        if(isset($request->get)){
            foreach ($request->get as $k => $v){
                $_GET[$k] = $v;
            }
        }

        $_FILES = [];
        if(isset($request->files)){
            foreach ($request->files as $k => $v){
                $_FILES[$k] = $v;
            }
        }

        $_POST = [];
        if(isset($request -> post)){
            foreach ($request->server as $k => $v){
                $_POST[$k] = $v;
            }
        }

//        日志落盘
        $this->writeLog();

        $_POST['http_server'] = $this->ws;
//    执行框架中的内容
        ob_start();
        try {
            think\Container::get('app', [APP_PATH])
                ->run()
                ->send();
        }catch (\Exception $e){
            // todo
        }
        $res = ob_get_contents();
        ob_end_clean();
        $response->end($res);
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $workerId
     * @param $data
     * @return string
     */
    public function onTask($serv,$taskId,$workerId,$data){
//        分发task任务机制,让不同的任务走不通的逻辑
        $obj = new app\common\lib\task\Task;
        $method = $data['method'];
        $flag = $obj -> $method($data['data'],$serv);

        return $flag; // 告诉worker进程
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $data
     */
    public function onFinish($serv,$taskId,$data){
        echo "taskId:{$taskId}\n";
        echo "finish-data-success:{$data}\n";
    }

    /**
     * 监听ws打开事件
     * @param $ws
     * @param $request
     */
    public function onOpen($ws,$request){
//        print_r($ws);
        \app\common\lib\redis\Predis::getInstance()->sAdd(config('redis.live_game_key'),$request->fd);
        var_dump($request->fd);
    }

    /**
     * 监听ws消息事件
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws,$frame){
        echo "server-push-message:{$frame->data}\n";
        $ws->push($frame->fd,"server-push:".date("Y-m-d H:i:s"));
    }

    /**
     * 监听关闭事件
     * @param $ws
     * @param $fd
     */
    public function onClose($ws,$fd){
//        fd 删除
        \app\common\lib\redis\Predis::getInstance()->sRem(config('redis.live_game_key'),$fd);
        echo "clientId:{$fd}\n";
    }

    public function writeLog(){
//        获取请求信息
        $data = array_merge(['data'=>date("Ymd H:i:s")],$_GET,$_POST,$_SERVER);
//        遍历写入信息,因为获取到信息是索引数组
        $logs = "";
        foreach ($data as $key => $value){
            $logs .= $key.":".$value." ";
        }
        swoole_async_writefile(APP_PATH.'../runtime/log/'.date("Ym")."/".date("d")."_access.log", $logs.PHP_EOL,function ($filename){
//            todo
        },FILE_APPEND);
    }
}

// 直接new来开启服务
new Ws();

说明:

  • 使用了swoole异步文件写入来实现高性能日志的写入
  • 在onRequest中进行日志的写入,其实就是每次连接成功的时候就获取这次请求的超全局变量信息$_GET, $_POST, $_SERVER然后写入
  • 需要注意favicon会被视为一次请求,因此需要在onRequest中把这个请求视为404,查看这个请求的方法是打印request -> server然后找到这个请求的索引是request_uri然后局把它的状态设置为404.
posted @ 2022-07-02 23:32  快乐的在一起  阅读(182)  评论(0编辑  收藏  举报