Easyswoole源码分析-4-start

作者: 会长__ | 来源:发表于2019-05-27 16:35 被阅读9次
    
    ////////////////////////////////////////////////////////////////////
    //                          _ooOoo_                               //
    //                         o8888888o                              //
    //                         88" . "88                              //
    //                         (| ^_^ |)                              //
    //                         O\  =  /O                              //
    //                      ____/`---'\____                           //
    //                    .'  \\|     |//  `.                         //
    //                   /  \\|||  :  |||//  \                        //
    //                  /  _||||| -:- |||||-  \                       //
    //                  |   | \\\  -  /// |   |                       //
    //                  | \_|  ''\---/''  |   |                       //
    //                  \  .-\__  `-`  ___/-. /                       //
    //                ___`. .'  /--.--\  `. . ___                     //
    //            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
    //      ========`-.____`-.___\_____/___.-`____.-'========         //
    //                           `=---='                              //
    //      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
    //         佛祖保佑       永无BUG       永不修改                     //
    ////////////////////////////////////////////////////////////////////
    

    1.简介

    启动算是框架的核心部分了,阅读起来有些地方理解起来还是有点困难的,这些部分单独拿出来解析。

    2.知识点

    1.apc_clear_cache
    2.opcache_reset
    3.final
    4.PHP中Closure类详解

    3. 核心代码

    start类下的exec方法的核心代码

    public function exec(array $args): ?string
    {
            // TODO: Implement exec() method.
            //---------------------------------1.清理apc缓存------------------------------
            Utility::opCacheClear();
            //---------------------------------2.展示Logo------------------------------
            $response = Utility::easySwooleLog();
            $mode = 'develop';
            //---------------------------------3.线上|开发配置------------------------------
            if(!Core::getInstance()->isDev()){
                $mode = 'produce';
            }
            $conf = Config::getInstance();
            //---------------------------------4.是否daemon化------------------------------
            if(in_array("d",$args) || in_array("daemonize",$args)){
                $conf->setConf("MAIN_SERVER.SETTING.daemonize", true);
            }
            //---------------------------------5.创建主服务------------------------------
            Core::getInstance()->createServer();
            $serverType = $conf->getConf('MAIN_SERVER.SERVER_TYPE');
            //---------------------------------6.cli展示信息------------------------------
            ·
            · 省略
            ·
            //---------------------------------7.启动------------------------------
            Core::getInstance()->start();
            return null;
    }
    

    3.清理apc缓存

    核心代码

    public static function opCacheClear()
    {
            if (function_exists('apc_clear_cache')) {
                // https://www.php.net/manual/zh/function.apc-clear-cache.php
                // 1.根据官方手册来看,apc_clear_cache函数如果传递的参数为omitted或者其它字符将会清除系统缓存
                // 2.如果运行在cli则只清除命令行缓存
                // 3.如果http请求则清除的是http缓存
                apc_clear_cache();
            }
            // https://www.jianshu.com/p/f089b6d19382
            if (function_exists('opcache_reset')) {
                opcache_reset();
            }
    }
    

    展示logo略略略
    线上|开发配置略略略
    是否daemon化略略略

    额。都略略略了,,,,其实核心部分在创建主服务。。。。

    4. 创建主服务

    Core::getInstance()->createServer();

    function createServer()
    {
            $conf = Config::getInstance()->getConf('MAIN_SERVER');
            //---------------------------------1.创建swoole server------------------------------
            ServerManager::getInstance()->createSwooleServer(
                $conf['PORT'],$conf['SERVER_TYPE'],$conf['LISTEN_ADDRESS'],$conf['SETTING'],$conf['RUN_MODEL'],$conf['SOCK_TYPE']
            );
            //---------------------------------2.注册默认的回调事件------------------------------
            $this->registerDefaultCallBack(ServerManager::getInstance()->getSwooleServer(),$conf['SERVER_TYPE']);
            //---------------------------------3.hook mainServerCreate方法------------------------------
            EasySwooleEvent::mainServerCreate(ServerManager::getInstance()->getMainEventRegister());
            //---------------------------------4.注册Console和crontab(这两个以后单独拿出来分析)------------------------------
            $this->extraHandler();
            return $this;
    }
    

    创建swoole server

    这里面的Dispatcher、Request、Response类后面单独拿出来介绍。写文章的时候会把人绕晕

    /**
         *  根据type创建不同的swoole服务,详细参数参考swoole手册
         *
         * @param $port
         * @param $type
         * @param string $address
         * @param array $setting
         * @param array ...$args
         * @return bool
         * CreateTime: 2019/5/27 下午3:11
         */
        function createSwooleServer($port,$type ,$address = '0.0.0.0',array $setting = [],...$args):bool
        {
            switch ($type){
                // https://wiki.swoole.com/wiki/page/p-server.html
                case EASYSWOOLE_SERVER:{
                    $this->swooleServer = new \swoole_server($address,$port,...$args);
                    break;
                }
                // https://wiki.swoole.com/wiki/page/327.html
                case EASYSWOOLE_WEB_SERVER:{
                    $this->swooleServer = new \swoole_http_server($address,$port,...$args);
                    break;
                }
                // https://wiki.swoole.com/wiki/page/397.html
                case EASYSWOOLE_WEB_SOCKET_SERVER:{
                    $this->swooleServer = new \swoole_websocket_server($address,$port,...$args);
                    break;
                }
                default:{
                    Trigger::getInstance()->error('"unknown server type :{$type}"');
                    return false;
                }
            }
            if($this->swooleServer){
                // https://wiki.swoole.com/wiki/page/13.html
                $this->swooleServer->set($setting);
            }
            return true;
        }
    

    注册默认的回调事件

    private function registerDefaultCallBack(\swoole_server $server,int $serverType)
        {
            //---------------------------------1.非swoole_server------------------------------
            if($serverType !== EASYSWOOLE_SERVER){
                         ···
                //---------------------------------1.1具体这里的Dispatcher有啥用还不清楚,等用到的时候再分析------------------------------
                $dispatcher = new Dispatcher($namespace,$depth,$max);
                $dispatcher->setControllerPoolWaitTime($waitTime);
                $httpExceptionHandler = Di::getInstance()->get(SysConst::HTTP_EXCEPTION_HANDLER);
                if(!is_callable($httpExceptionHandler)){
                    $httpExceptionHandler = function ($throwable,$request,$response){
                        $response->withStatus(Status::CODE_INTERNAL_SERVER_ERROR);
                        $response->write(nl2br($throwable->getMessage()."\n".$throwable->getTraceAsString()));
                        Trigger::getInstance()->throwable($throwable);
                    };
                    Di::getInstance()->set(SysConst::HTTP_EXCEPTION_HANDLER,$httpExceptionHandler);
                }
                //---------------------------------1.2设置异常处理------------------------------
                $dispatcher->setHttpExceptionHandler($httpExceptionHandler);
                //---------------------------------1.3注册回调onRequest方法------------------------------
                EventHelper::on($server,EventRegister::onRequest,function (\swoole_http_request $request,\swoole_http_response $response)use($dispatcher){
                    $request_psr = new Request($request);
                    $response_psr = new Response($response);
                    try{
                        //---------------------------------1.4 hook EasySwooleEvent的onRequest方法------------------------------
                        if(EasySwooleEvent::onRequest($request_psr,$response_psr)){
                            $dispatcher->dispatch($request_psr,$response_psr);
                        }
                    }catch (\Throwable $throwable){
                        call_user_func(Di::getInstance()->get(SysConst::HTTP_EXCEPTION_HANDLER),$throwable,$request_psr,$response_psr);
                    }finally{
                        try{
                            //---------------------------------1.5 hook EasySwooleEvent的afterRequest方法------------------------------
                            EasySwooleEvent::afterRequest($request_psr,$response_psr);
                        }catch (\Throwable $throwable){
                            call_user_func(Di::getInstance()->get(SysConst::HTTP_EXCEPTION_HANDLER),$throwable,$request_psr,$response_psr);
                        }
                    }
                    $response_psr->__response();
                });
            }
            //---------------------------------2 注册onTask方法------------------------------
            EventHelper::on($server,EventRegister::onTask,function (\swoole_server $server, Task $task){
                $finishData = null;
                $taskObj = $task->data;
    
                //---------------------------------2.1 判断是否为使用快速任务模板------------------------------
                // 可通过继承EasySwoole\EasySwoole\Swoole\Task\QuickTaskInterface,增加run方法,即可实现一个任务模板,通过直接投递类名运行任务:
                if(is_string($taskObj) && class_exists($taskObj)){
                              ···
                }
                //---------------------------------2.2 判断是否为异步任务模板------------------------------
                // 当任务比较复杂,逻辑较多而且固定时,可以预先创建任务模板,并直接投递任务模板,以简化操作和方便在多个不同的地方投递相同的任务,首先需要创建一个任务模板
                if($taskObj instanceof AbstractAsyncTask){
                             ···
                //---------------------------------2.3 SuperClosure是否继承SuperClosure(这里的知识点很重要,也不是很好理解,Closure类)------------------------------
                }else if($taskObj instanceof SuperClosure){
                            ···
                //---------------------------------2.4如果传递的为方法 ------------------------------
                }else if(is_callable($taskObj)){
                            ···
                }
                finish :{
                    $task->finish($finishData);
                }
            });
            //---------------------------------3 注册onFinish方法 ------------------------------
            EventHelper::on($server,EventRegister::onFinish,function (\swoole_server $serv, int $task_id,$data){
                return $data;
            });
    
            //---------------------------------4 注册默认的worker start ------------------------------
            EventHelper::registerWithAdd(ServerManager::getInstance()->getMainEventRegister(),EventRegister::onWorkerStart,function (\swoole_server $server,$workerId){
              ···
            });
        }
    

    5.cli展示信息

    额。这里自己去看吧。

    6. 启动

    Core::getInstance()->start();

    function start()
        {
            //给主进程也命名
            $serverName = Config::getInstance()->getConf('SERVER_NAME');
            if(PHP_OS != 'Darwin'){
                cli_set_process_title($serverName);
            }
            //启动
            ServerManager::getInstance()->start();
        }
    

    ServerManager::getInstance()->start();

    function start()
        {
            // 将EventHelper::registerWithAdd注册的回调绑定到服务,启动的时候只注册了workerStart
            $events = $this->getMainEventRegister()->all();
            foreach ($events as $event => $callback){
                $this->getSwooleServer()->on($event, function (...$args) use ($callback) {
                    foreach ($callback as $item) {
                        call_user_func($item,...$args);
                    }
                });
            }
            //  子服务,启动的时候只有CONSOLE(这里单独拿出来讲)
            $this->registerSubPortCallback();
            $this->isStart = true;
            // 启动
            $this->getSwooleServer()->start();
        }
    

    7.结语

    主要记录学习,不当地方请指出

    8.相关连接

    Easyswoole手册
    Swoole手册

    相关文章

      网友评论

        本文标题:Easyswoole源码分析-4-start

        本文链接:https://www.haomeiwen.com/subject/blqhtctx.html