EasySwoole核心Core分析(二):createServer&start方法

我们之前分析了CommandRunner类,它会去执行一些具体的命令.当我们输入php easyswoole start的时候,将会去执行EasySwoole\EasySwoole\Command\DefaultCommand\Start类中的exec方法.

public function exec(array $args): ?string
{
    // 清除Opcahce缓存和apc缓存
    Utility::opCacheClear();
    $mode = 'develop';
    // 判断是否为dev环境
    if (!Core::getInstance()->isDev()) {
        $mode = 'produce';
    }
    // 获取config实例
    $conf = Config::getInstance();
    // 判断是否为守护进程
    if (in_array("d", $args) || in_array("daemonize", $args)) {
        $conf->setConf("MAIN_SERVER.SETTING.daemonize", true);
    }
    // 创建服务
    Core::getInstance()->createServer();
    ...
    // 将服务器信息打印在终端
    echo $response;
    // 启动服务
    Core::getInstance()->start();
    return null;
}

我们之前都是在初始化日志系统、注册注册错误回调,还没有创建Swoole相关服务,那么创建Swoole实例的部分在哪呢?

Core::getInstance()->createServer() 顾名思义创建服务

function createServer()
{
    $conf = Config::getInstance()->getConf('MAIN_SERVER');
    // 创建Swoole服务
    ServerManager::getInstance()->createSwooleServer(
        $conf['PORT'], $conf['SERVER_TYPE'], $conf['LISTEN_ADDRESS'], $conf['SETTING'], $conf['RUN_MODEL'], $conf['SOCK_TYPE']
    );
    // 注册默认回调事件
    $this->registerDefaultCallBack(ServerManager::getInstance()->getSwooleServer(), $conf['SERVER_TYPE']);
    // hook 全局的mainServerCreate事件
    EasySwooleEvent::mainServerCreate(ServerManager::getInstance()->getMainEventRegister());
    // 注册crontab、Task进程
    $this->extraHandler();
    return $this;
}

ServerManager::getInstance()->createSwooleServer() 这里又使用ServerManager类的方法,这篇里我们只需要知道它能创建一个Swoole服务即可(后续会专门介绍内部实现)

$this->registerDefaultCallBack() 该方法用于注册主服务的事件,我们知道Swoole的Server有多个事件,我们需要去设置相应的回调.

private function registerDefaultCallBack(\swoole_server $server, int $serverType)
    {
        // 判断是否为HTTP服务或WebSocket服务, 绑定OnRequest事件
        if (in_array($serverType, [EASYSWOOLE_WEB_SERVER, EASYSWOOLE_WEB_SOCKET_SERVER], true)) {
            // 获取命名空间
            $namespace = Di::getInstance()->get(SysConst::HTTP_CONTROLLER_NAMESPACE);
            if (empty($namespace)) {
                $namespace = 'App\\HttpController\\';
            }
            // 获取控制器最大深度
            $depth = intval(Di::getInstance()->get(SysConst::HTTP_CONTROLLER_MAX_DEPTH));
            $depth = $depth > 5 ? $depth : 5;
            // 获取最大数量
            $max = intval(Di::getInstance()->get(SysConst::HTTP_CONTROLLER_POOL_MAX_NUM));
            z($max);
            if ($max == 0) {
                $max = 500;
            }
            // 获取等待时间
            $waitTime = intval(Di::getInstance()->get(SysConst::HTTP_CONTROLLER_POOL_WAIT_TIME));
            if ($waitTime == 0) {
                $waitTime = 5;
            }
            // 初始化路由分发器
            $dispatcher = new Dispatcher($namespace, $depth, $max);
            // 设置等待时间
            $dispatcher->setControllerPoolWaitTime($waitTime);
            // 获取HTTP异常全局处理方式
            $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);
            }
            // 为分发器也设置异常处理方法
            $dispatcher->setHttpExceptionHandler($httpExceptionHandler);

            // 为创建的Server注册Request事件, EventHelper类封装了Swoole的Server的on、add、set方法
            EventHelper::on($server, EventRegister::onRequest, function (\swoole_http_request $request, \swoole_http_response $response) use ($dispatcher) {
                $request_psr = new Request($request); // 生成PSR请求规范
                $response_psr = new Response($response); // 生成PSR响应规范
                try {
                    // 如果为true则分发路由, 这里的onRequest和Swoole的事件是两码事,不要弄混淆了
                    if (EasySwooleEvent::onRequest($request_psr, $response_psr)) {
                        // 分发路由, 执行HTTP控制器里__hook方法,将响应结果存入Response对象
                        $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 {
                        // 处理全局Http 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();
            });
        }

        // 获取主服务的事件对象
        $register = ServerManager::getInstance()->getMainEventRegister();
        //注册进程启动事件
        EventHelper::registerWithAdd($register, EventRegister::onWorkerStart, function (\swoole_server $server, $workerId) {
            // 为Work进程设置名字
            if (!in_array(PHP_OS, ['Darwin', 'CYGWIN', 'WINNT'])) {
                $name = Config::getInstance()->getConf('SERVER_NAME');
                if (($workerId < Config::getInstance()->getConf('MAIN_SERVER.SETTING.worker_num')) && $workerId >= 0) {
                    $type = 'Worker';
                    cli_set_process_title("{$name}.{$type}.{$workerId}");
                }
            }
        });
        // 注册进程退出事件
        EventHelper::registerWithAdd($register, $register::onWorkerExit, function () {
            // 清除当前工作进程内的所有定时器
            Timer::clearAll();
        });
    }

EasySwoole里提供了一个EventRegister类,里面声明了Swoole Server的事件.

class EventRegister extends MultiContainer
{
    const onStart = 'start';
    const onShutdown = 'shutdown';
    const onWorkerStart = 'workerStart';
    const onWorkerStop = 'workerStop';
    const onWorkerExit = 'workerExit';
    const onTimer = 'timer';
    const onConnect = 'connect';
    const onReceive = 'receive';
    const onPacket = 'packet';
    const onClose = 'close';
    const onBufferFull = 'bufferFull';
    const onBufferEmpty = 'bufferEmpty';
    const onTask = 'task';
    const onFinish = 'finish';
    const onPipeMessage = 'pipeMessage';
    const onWorkerError = 'workerError';
    const onManagerStart = 'managerStart';
    const onManagerStop = 'managerStop';
    const onRequest = 'request';
    const onHandShake = 'handShake';
    const onMessage = 'message';
    const onOpen = 'open';
    
    ...
}

registerDefaultCallBack方法里还会初始化一个Dispatcher类,该类用于分发请求到相应的控制器.(路由组件基于fastRoute).这里我们只需要知道它是干啥的就可以了.

默认只针对HTTP服务或WebSocket服务创建OnRequset事件,最后还设置了OnWorkStartOnWorkExit事件,其他服务或者是需要处理其他事件,可以在根目录的EasySwooleEvent类中mainServerCreate方法创建,例如是一个websocket服务需要自己注册一个OnMessage事件,例如:

public static function mainServerCreate(EventRegister $register)
{
    $register->set(EventRegister::onMessage, function (\swoole_websocket_server $server, \swoole_websocket_frame $frame) {
        $server->push($frame->fd, "over");
    });
}

最后在$this->extraHandler方法里注册crontab和Task进程,到此createServer方法我们分析完毕.

我们的Start方法调用ServerManager::getInstance()->start()启动整个服务.到这里我们Swoole实例已经跑起来了.

如果没有仔细跟读源码,会对 DI,ServerManager,Dispatcher,Crontab,TaskManager的实现很模糊,甚至会读不懂上下文.在后续的分析中,会专门分析其具体实现.循序渐进而不是一篇到底.这样可能读起来更困难.