EasySwoole服务启动流程及主要设计流程源码分析EasySwoole服务时,命令实际到达的文件为easyswooleproject\vendor\easyswoole\easyswoole\bin\easyswoole.命令启动执行的整体流程如下:主要方法是:serverStart($options);,其重要的执行代码如下:$conf=Conf::getInstance();$inst=Core::getInstance()->初始化();$inst->运行();初始化Conf,即Config对象(Config类是单例对象),加载全局Configuration信息,默认配置Config.php内容如下:return['SERVER_NAME'=>"EasySwoole",'MAIN_SERVER'=>['HOST'=>'0.0.0.0','PORT'=>9501,'SERVER_TYPE'=>\EasySwoole\Core\Swoole\ServerManager::TYPE_WEB_SERVER,'SOCK_TYPE'=>SWOOLE_TCP,//这个配置项SERVER_TYPE的值为TYPE_SERVER时有效'RUN_MODEL'=>SWOOLE_PROCESS,'SETTING'=>['task_worker_num'=>8,//异步任务进程'task_max_request'=>10,'max_request'=>5000,//强烈建议设置这个配置项'worker_num'=>8],],'DEBUG'=>true,'TEMP_DIR'=>null,//如果不配置,默认帧初始化'LOG_DIR'=>null,//如果不配置,默认帧初始化'EASY_CACHE'=>['PROCESS_NUM'=>1,//如果不想开启,设置为0'PERSISTENT_TIME'=>0//如果需要定时数据登陆,请设置相应的时间段,单位秒],'CLUSTER'=>['enable'=>false,'token'=>null,'broadcastAddress'=>['255.255.255.255:9556'],'listenAddress'=>'0.0.0.0','listenPort'=>'9556','broadcastTTL'=>5,'nodeTimeout'=>10,'nodeName'=>'easySwoole','nodeId'=>null]];执行入口文件Code.php对象的initialize()方法执行入口文件Code.php对象的run()方法ps:这里插一句说明EasySwoole中的单例类复用了相同的traittraitSingleton{privatestatic$实例;静态函数getInstance(...$args){if(!isset(self::$instance)){self::$instance=newstatic(...$args);}返回自我::$实例;}}入口文件Easywechat真正的入口文件是EasySwoole\Core\Core。上面提到,当命令启动时,会执行如下代码:Core::getInstance();$inst=Core::getInstance()->initialize();$inst->run();在EasySwoole的整个生命周期中,Core对象只会被实例化一次,代码初始化如下:publicfunction__construct(){defined('SWOOLE_VERSION')或define('SWOOLE_VERSION',intval(phpversion('swoole')));defined('EASYSWOOLE_ROOT')或define('EASYSWOOLE_ROOT',realpath(getcwd()));if(file_exists(EASYSWOOLE_ROOT.'/EasySwooleEvent.php')){require_onceEASYSWOOLE_ROOT.'/EasySwooleEvent.php';//引入全局初始化事件类}$this->sysDirectoryInit();//设置temp目录和log目录,路径可配置}定义全局宏SWOOLE_VERSION和EASYSWOOLE_ROOT引入全局初始化事件类EasySwooleEvent.php$this->sysDirectoryInit();设置temp目录和log目录,路径可以通过Core类中的initialize方法配置:publicfunctioninitialize():Core{Di::getInstance()->set(SysConst::VERSION,'2.1.2');Di::getInstance()->set(SysConst::HTTP_CONTROLLER_MAX_DEPTH,3);EasySwooleEvent::frameInitialize();$this->errorHandle();返回$这个;}DI容器注入SysConst::VERSION和SysConst::HTTP_CONTROLLER_MAX_DEPTH的值执行全局事件类EasySwooleEvent::frameInitialize();事件$this->errorHandle();注册系统中set_error_handler和register_shutdown_functionCore类的run方法是核心函数:publicfunctionrun():void{ServerManager::getInstance()->start();}实例化ServerManager类,执行start()启动整个服务服务管理类ServerManagerServerManager是一个单例对象。在整个EasySwoole生命周期中,ServeManager对象只会被实例化一次。ServeManager的run方法做了以下几件事:缓存::getInstance();Cluster::getInstance()->run();CronTab::getInstance()->run();$this->attachListener();$this->isStart=true;$this->getServer()->start();}createMainServer()创建主服务,初始化缓存服务缓存,并添加对应的CacheProcess(easyswoole的缓存服务是基于swoole_process管道通信的,后面会专门分析系统组件缓存的源码)Cluster集群模式注册(感兴趣的可以通过链接查看)CronTab服务开启,然后我们会讲到使用crontabattachListener事件监听,子服务多端口监听$this->getServer()->start();调用swoole_server的start方法正式启动Easyswoole服务ServerManager类的createMainServer()方法:(1)读取配置,创建对应的swoole_server服务用例self::TYPE_SERVER:{$this->mainServer=new\swoole_server($host,$port,$runModel,$sockType);休息;}caseself::TYPE_WEB_SERVER:{$this->mainServer=new\swoole_http_server($host,$port,$runModel,$sockType);休息;}caseself::TYPE_WEB_SOCKET_SERVER:{$this->mainServer=new\swoole_websocket_server($host,$port,$runModel,$sockType);休息;}default:{Trigger::throwable(new\Exception("unknownservertype:{$conf['SERVER_TYPE']}"));}}(2)注册事件,onWorker,onTask、onFinish、onRequest等;还有easySwoole事件mainServerCreate,开发者可以在mainServerCreate事件中设置Crontab服务$register=newEventRegister();//事件容器$this->finalHook($register);EasySwooleEvent::mainServerCreate($this,$register);$events=$register->all();(3)在事件注册的过程中,还做了以下操作:实例化对象池开发者可以在这里通过配置实例化mysql连接池等://实例化对象池管理PoolManager::getInstance();PoolManager::getInstance()->__workerStartHook($workerId);(4)在onRequest事件中,同样执行EasySwooleEvent的onRequest和afterAction,这里开发者可以自定义处理代码,比如统一退出方式EasySwooleEvent::onRequest($request_psr,$response_psr);$dispatcher->dispatch($request_psr,$response_psr);EasySwooleEvent::afterAction($request_psr,$response_psr);在ServerManager中注册Cache::getInstance()全局跨进程Cache:function__construct(){$num=intval(Config::getInstance()->getConf("EASY_CACHE.PROCESS_NUM"));如果($num<=0){返回;}$this->cliTemp=newSplArray();//如果是在主服务中创建,不是单元测试调用::EXCHANGE_TABLE_NAME,['data'=>['type'=>Table::TYPE_STRING,'size'=>10*1024],'microTime'=>['type'=>Table::TYPE_STRING,'size'=>15]],2048);$this->processNum=$num;对于($i=0;$i<$num;$i++){ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class);}}}缓存服务基于swoole_table实现全局数据的共享和传递以上是EasySwoole服务启动流程的主要设计,包括了各个组件的实例化,如PoolManager(对象池)、缓存、CronTab等。
