前文連接,閱讀的時候最好參照EasySwoole2.1.2的源碼
$inst->run();//啟動服務
這里實際調用的是Core的start方法ServerManager::getInstance()->start();
這個方法主要是啟動swoole服務的
//創建主服務 $this->createMainServer();
在這塊代碼里主要是核心,是在swoole執行start服務前設置相關配置以及配置相關回調函數。具體代碼如下
先給服務器配置相關運行參數
$conf = Config::getInstance()->getConf("MAIN_SERVER");//獲取Config.php 中配置的MAIN_SERVER數組 $runModel = $conf['RUN_MODEL'];//獲取運行模式 默認是SWOOLE_PROCESS模式,使用進程模式,業務代碼在Worker進程中執行 $host = $conf['HOST'];//獲取運行的host 'HOST'=>'0.0.0.0', $port = $conf['PORT'];//獲取配置的運行端口為9501 'PORT'=>9501, $setting = $conf['SETTING'];//這里設置的相關的配置項,這些配置做一些解釋,參照https://wiki.swoole.com/wiki/page/274.html 'SETTING'=>[ 'task_worker_num' => 8, //配置Task進程的數量,配置此參數后將會啟用task功能。所以Server務必要注冊onTask、onFinish2個事件回調函數。如果沒有注冊,服務器程序將無法啟動。 'task_max_request'=>10,//設置task進程的最大任務數。一個task進程在處理完超過此數值的任務后將自動退出。這個參數是為了防止PHP進程內存溢出。如果不希望進程自動退出可以設置為0,炒雞重要,進程中的數據,如果有一個global數組,或者全局變量,不設置這個就會不回收最終導致內存溢出 'max_request'=>5000,//設置worker進程的最大任務數,這個和task_max_request功能一樣,為了解決PHP進程內存溢出問題 'worker_num'=>8//設置啟動的Worker進程數 ], //其實這里還有2個配置,是前文中提到的,在前文19行$this->sysDirectoryInit();會初始化配置pid_file和log_file pid_file //在Server啟動時自動將master進程的PID寫入到文件,在Server關閉時自動刪除PID文件。 log_file //指定swoole錯誤日志文件。在swoole運行期發生的異常信息會記錄到這個文件中。默認會打印到屏幕。 $sockType = $conf['SOCK_TYPE'];//指定當前運行的服務是什么服務器。有tcp服務,http服務,websocket服務。默認是tcp服務 switch ($conf['SERVER_TYPE']){ case self::TYPE_SERVER:{ $this->mainServer = new \swoole_server($host,$port,$runModel,$sockType);//創建mainServer,這里創建了一個tcp服務器 break; } case self::TYPE_WEB_SERVER:{ $this->mainServer = new \swoole_http_server($host,$port,$runModel,$sockType);//web方式是默認 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']}")); } } $this->mainServer->set($setting);//將上面的相關服務啟動配置到mainServer
創建默認的事件注冊器,給服務注冊默認的是事件處理函數
$register = new EventRegister(); $this->finalHook($register); EasySwooleEvent::mainServerCreate($this,$register);//這里是框架全局事件mainServerCreate主服務創建事件 $events = $register->all(); //然后循環給swoole服務器綁定回調函數。這里同一個回調方法設置多個回調函數 foreach ($events as $event => $callback){ $this->mainServer->on($event, function () use ($callback) { $ret = []; $args = func_get_args(); foreach ($callback as $item) { array_push($ret,Invoker::callUserFuncArray($item, $args)); } if(count($ret) > 1){ return $ret; } return array_shift($ret); }); }
這里提一下finalHook具體做了什么操作
$this->finalHook($register);
//實例化對象池管理 PoolManager::getInstance(); //register,先綁定一個workerStart回調函數。此事件在Worker進程/Task進程啟動時發生。這里創建的對象可以在進程全局周期內使用。 $register->add($register::onWorkerStart,function (\swoole_server $server,int $workerId){ PoolManager::getInstance()->__workerStartHook($workerId); $workerNum = Config::getInstance()->getConf('MAIN_SERVER.SETTING.worker_num'); $name = Config::getInstance()->getConf('SERVER_NAME'); if(PHP_OS != 'Darwin'){ if($workerId <= ($workerNum -1)){//判斷當前是否是worker進程 $name = "{$name}_Worker_".$workerId; }else{//這個是task進程 $name = "{$name}_Task_Worker_".$workerId; } cli_set_process_title($name);//設置當前的進程名稱 //圖片 } }); //EventHelper 是一個框架提供的默認的事件處理函數(這些放到后面具體講述) EventHelper::registerDefaultOnTask($register);//注冊默認的task回調,處理task任務的具體函數 EventHelper::registerDefaultOnFinish($register);//注冊默認的task任務完成后的回調 EventHelper::registerDefaultOnPipeMessage($register);//注冊pipeMessage回調函數 $conf = Config::getInstance()->getConf("MAIN_SERVER"); //如果是http服務器或者websocket,需要注冊request回調函數 if($conf['SERVER_TYPE'] == self::TYPE_WEB_SERVER || $conf['SERVER_TYPE'] == self::TYPE_WEB_SOCKET_SERVER){ if(!$register->get($register::onRequest)){ EventHelper::registerDefaultOnRequest($register);//這里包含了請求,然后路由解析,處理返回的功能。就跟一般web框架類似 } }
系統啟動后,在worker啟動的時候,會進行改名的操作,如下圖
最后注冊相關的cache監聽端口等就啟動swoole服務了。
Cache::getInstance(); //這里注冊Cache Cluster::getInstance()->run(); //實現RPC CronTab::getInstance()->run(); //定時任務 $this->attachListener();//Swoole提供了swoole_server::addListener來增加監聽的端口。業務代碼中可以通過調用swoole_server::connection_info來獲取某個連接來自於哪個端口。這里框架啟動的時候host配置的是0.0.0.0 所以監聽所有地址,就沒必要設置這個了 $this->isStart = true; $this->getServer()->start();//啟動swoole服務器,在這之前創建的對象都在程序全局期中
下篇文章介紹TableManager。因為它在很多地方都被用到了。