本文主要講解EasySwoole 服務的啓動過程,會經過源碼片斷講解主體的設計流程php
當咱們經過php easyswoole start
啓動EasySwoole 服務時,命令真正到達的文件是 easyswoole項目\vendor\easyswoole\easyswoole\bin\easyswoole
,命令start執行的總體流程以下圖:html
主要方法爲:serverStart($options);
,其重要執行代碼以下:node
$conf = Conf::getInstance(); $inst = Core::getInstance()->initialize(); $inst->run();
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 ] ];
initialize()
方法run()
方法ps:此處插入說明一個點,EasySwoole中單例類都複用同一個trait
mysql
trait Singleton { private static $instance; static function getInstance(...$args) { if(!isset(self::$instance)){ self::$instance = new static(...$args); } return self::$instance; } }
Easywechat 真實入口文件爲EasySwoole\Core\Core
,上述已經說到命令啓動時,執行了如下代碼:web
Core::getInstance(); $inst = Core::getInstance()->initialize(); $inst->run();
在整個EasySwoole生命週期中,Core對象只會被實例化一次,Code的初始化作了以下操做:sql
public function __construct() { defined('SWOOLE_VERSION') or define('SWOOLE_VERSION',intval(phpversion('swoole'))); defined('EASYSWOOLE_ROOT') or define('EASYSWOOLE_ROOT',realpath(getcwd())); if(file_exists(EASYSWOOLE_ROOT.'/EasySwooleEvent.php')){ require_once EASYSWOOLE_ROOT.'/EasySwooleEvent.php'; //引入全局初始化事件類 } $this->sysDirectoryInit(); //設置temp目錄和log目錄,路徑可配置化 }
SWOOLE_VERSION
和 EASYSWOOLE_ROOT
EasySwooleEvent.php
$this->sysDirectoryInit();
設置temp目錄和log目錄,路徑可配置化Core類中的initialize
方法:緩存
public function initialize():Core { Di::getInstance()->set(SysConst::VERSION,'2.1.2'); Di::getInstance()->set(SysConst::HTTP_CONTROLLER_MAX_DEPTH,3); EasySwooleEvent::frameInitialize(); $this->errorHandle(); return $this; }
SysConst::VERSION
和 SysConst::HTTP_CONTROLLER_MAX_DEPTH
的值EasySwooleEvent::frameInitialize();
事件$this->errorHandle();
註冊系統中的set_error_handler、register_shutdown_functionCore類的run方法爲核心功能:websocket
public function run():void { ServerManager::getInstance()->start(); }
ServerManager
類,並執行start()
啓動整個服務ServerManager
是一個單例對象,在整個EasySwoole生命週期中,ServeManager
對象只會被實例化一次.ServeManager
的 run
方法幹了下面幾件事:swoole
public function start():void { $this->createMainServer(); Cache::getInstance(); Cluster::getInstance()->run(); CronTab::getInstance()->run(); $this->attachListener(); $this->isStart = true; $this->getServer()->start(); }
createMainServer()
建立主服務cache
,添加對應的CacheProcess
。(Easyswoole的緩存服務是基於swoole_process
的管道通訊,後續會專門解析下系統組件cache
的源碼)Cluster
集羣模式的註冊 (有興趣的能夠經過連接看看)CronTab
服務開啓,後面說下crontab的使用attachListener
事件監聽,子服務多端口監聽$this->getServer()->start();
調用swoole_server
的start方法,正式啓動Easyswoole
服務ServerManager
類的createMainServer()
方法:框架
(1)讀取配置,建立對應的swoole_server服務
case self::TYPE_SERVER:{ $this->mainServer = new \swoole_server($host,$port,$runModel,$sockType); break; } case self::TYPE_WEB_SERVER:{ $this->mainServer = new \swoole_http_server($host,$port,$runModel,$sockType); break; } case self::TYPE_WEB_SOCKET_SERVER:{ $this->mainServer = new \swoole_websocket_server($host,$port,$runModel,$sockType); break; } default:{ Trigger::throwable(new \Exception("unknown server type :{$conf['SERVER_TYPE']}")); } }
(2)註冊事件,onWorker、onTask、onFinish、onRequest
等;還有easySwoole
事件mainServerCreate
,開發者能夠在mainServerCreate
事件設置Crontab
服務等
$register = new EventRegister();//事件容器 $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")); if($num <= 0){ return; } $this->cliTemp = new SplArray(); //如果在主服務建立,而非單元測試調用 if(ServerManager::getInstance()->getServer()){ //建立table用於數據傳遞 TableManager::getInstance()->add(self::EXCHANGE_TABLE_NAME,[ 'data'=>[ 'type'=>Table::TYPE_STRING, 'size'=>10*1024 ], 'microTime'=>[ 'type'=>Table::TYPE_STRING, 'size'=>15 ] ],2048); $this->processNum = $num; for ($i=0;$i < $num;$i++){ ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class); } } }
Cache
服務基於 swoole_table
實現全局數據共享和傳遞。
以上是EasySwoole
服務啓動過程當中的主體設計,其中包括了各類組件的實例化,如PoolManager(對象池)、cache、CronTab
等。