做者:bromine
连接:https://www.jianshu.com/p/e63...
來源:简书
著做权归做者全部,本文已得到做者受权转载,并对原文进行了从新的排版。
Swoft Github: https://github.com/swoft-clou...php
不一样于PHP-FPM每次请求都会加载一次PHP代码,常驻型应用只会读取一次源文件,为了不每次发布/调试代码都须要手动重启Swoft应用,Swoft提供了自动重载代码的功能。git
Swoft注册了一个名为reload的Process,该进程会在系统引导的最后一个阶段,即Swoole启动前启动。该Process会启动名为reload的Beangithub
//Swoft\Process\Bootstrap\Process\ReloadProcess.php /** * Relaod process * * @Process(name="reload", boot=true) */ class ReloadProcess implements ProcessInterface { /** * @param \Swoft\Process\Process $process */ public function run(SwoftProcess $process) { $pname = App::$server->getPname(); $processName = sprintf('%s reload process', $pname); $process->name($processName); /* @var \Swoft\Process\Bootstrap\Reload $relaod */ $relaod = App::getBean(Reload::class); $relaod->run(); } //..... }
//\Swoft\Process\Bootstrap\Reload::class /** * @Bean() */ class Reload { //code ..... /** * 启动监听 */ public function run() { $server = App::$server; while (true) { sleep($this->interval); //FileHelper::md5File()负责递归的计算文件夹的md5,其实更名为FileHelper::md5Dir()更合适,由于他不接受非目录的文件做为参数 $md5File = FileHelper::md5File($this->watchDir);//$this->watchDir固定为@app别名对应的文件夹 if (strcmp($this->md5File, $md5File) !== 0) { echo "Start reloading...\n"; $server->isRunning(); //md5和上次不一致就通知swoole重启服务 $server->getServer()->reload(); echo "Reloaded\n"; } $this->md5File = $md5File; } } }
代码自动重载的机制也很简单,每间隔几秒递归的计算@app目录下全部php文件的哈希值,发现文件夹的md5和以前的值有差异则通知Swoole重启worker进程。segmentfault
Swoole会通知各个worker重启,触发Swoole事件WorkerStart
,具体的回调事件以下swoole
namespace Swoft\Bootstrap\Server\ServerTrait.php; /** * OnWorkerStart event callback * * @param Server $server server * @param int $workerId workerId * @throws \InvalidArgumentException */ public function onWorkerStart(Server $server, int $workerId) { // Init Worker and TaskWorker $setting = $server->setting; $isWorker = false; if ($workerId >= $setting['worker_num']) { // TaskWorker ApplicationContext::setContext(ApplicationContext::TASK); ProcessHelper::setProcessTitle($this->serverSetting['pname'] . ' task process'); } else { // Worker $isWorker = true; ApplicationContext::setContext(ApplicationContext::WORKER); ProcessHelper::setProcessTitle($this->serverSetting['pname'] . ' worker process'); } //触发一个Swoft服务事件```SwooleEvent::ON_START```,其监听者使用@ServerListener(event=SwooleEvent::ON_START)声明 $this->fireServerEvent(SwooleEvent::ON_WORKER_START, [$server, $workerId, $isWorker]); //主要是从新扫描加载注解和Bean的重载 $this->beforeWorkerStart($server, $workerId, $isWorker); }
Swoft源码剖析系列目录: https://segmentfault.com/a/11...