Swoft source code analysis-code automatic update mechanism

  php, swoole

Author:bromine
Links:https://www.jianshu.com/p/e63 …
Source: Simple Book
The copyright belongs to the author. This article has been reprinted with the authorization of the author and the original text has been rearranged.
Swoft Github:https://github.com/swoft-clou …

Preface

Unlike PHP-FPM, which loads PHP code once per request, resident applications only read the source file once. In order to avoid manually restarting Swoft application every time code is released/debugged, Swoft provides the function of automatically reloading code.

File overload management process

Swoft has registered a Process called reload, which will start before the last stage of system boot, namely, Swoole. The Process starts a Bean named reload.

//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();
    }
    //.....
}

File update listening Bean

//\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;
        }
    }
}

The mechanism of automatic code reloading is also very simple. Hash values of all php files in the @app directory are calculated recursively every few seconds. If the md5 value of the folder is found to be different from the previous value, Swoole is notified to restart the worker process.

Swoole worker event

Swoole will notify each worker to restart, triggering the Swoole event.WorkerStartThe specific callback events are as follows

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 source code analysis series catalog:https://segmentfault.com/a/11 …