master-worker常驻型程序代码修改哪些需要重启master或者worker


之前在yii的项目里用redis作为消息队列,现在很多任务需要延迟需求,于是把之前redis的消息队列替换成了rabbitmq

于是使用yii的yii2-queue这个组件

但是由于提供的yii queue/listen是个单进程的消费,而且也不是守护进程,如果有个任务阻塞,就会对其它的任务有影响,开多个又难以管理

于是使用master-worker的方式 开多个worker干活,master监控worker状态

但是进程常驻的程序 又牵扯到代码修改了重启的问题
比如 在master启动就已经加载到内存的程序代码 不重启master是无法得到修改的变更的

下面例子来演示哪些代码需要重启,哪些不需要

这里使用的是从项目里抽出来的简要的进程管理组件

composer require hkui/process_manager

job.php

class job
{
    public function do($obj){

        $i=0;
        while(true){
            $i++;
            echo posix_getpid()."=".$i."-job-".A.PHP_EOL;
            sleep(2);
            $obj->isExit($i);
        }
    }
}

demo.php

require '../../../vendor/autoload.php';
use ProcessManager\Process;

define("A","456");
class demo extends Process
{
    public function runJob($worker, $index)
    {

        \swoole_set_process_name(sprintf('%s-worker-%d', 'test',$index));
        include 'job.php';
        $job=new job();
        $job->do($this);
    }
}

if(count($argv)<3){
    exit( "params lost".PHP_EOL);
}
$process_name=$argv[1];
$worker_num=3;
if(isset($argv[3])){
    $worker_num=intval($argv[3]);
}
$cmd=$argv[2];
$config=[
    'process_name'=>$process_name,
    'worker_num'=>$worker_num,
    'out_file'=>'/tmp/out',
    'max_run_time'=>10  //运行10个后自己退出,然后master补上

];
$process=new demo($config);
echo posix_getpid().PHP_EOL;
$process->run($cmd);
开启1个master3个worker
php demo.php test start 3

[root@6fb38402a4c6 process_manager]# php demo.php test status
9982
Array
(
    [0] => 9979 9980 9981
    [1] => USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    [2] => root      9882  0.0  0.1 144952  7420 ?        Ss   08:42   0:00 test-master
    [3] => root      9979  0.0  0.1 147004  9212 ?        S    08:49   0:00  \_ test-worker-1
    [4] => root      9980  0.0  0.1 147004  9212 ?        S    08:49   0:00  \_ test-worker-2
    [5] => root      9981  0.0  0.1 147004  9212 ?        S    08:49   0:00  \_ test-worker-0
)

修改常量A的值,worker在重启(运行满10次 或者执行 php demo.php test reload) 后,输出的结果不会体现出A的修改变更
但是修改 
job.php里runJob里的输出,worker在重启后会执行最新的代码
如果我们把 include 'job.php'; 拿到外面
demo部分替换成

define("A","456");
include 'job.php';

class demo extends Process
{
    public function runJob($worker, $index)
    {

        \swoole_set_process_name(sprintf('%s-worker-%d', 'test',$index));

        $job=new job();
        $job->do($this);
    }
}
这时修改job代码后,worker重启也不会生效了

runJob里的代码都是子进程worker里的代码
我们在最开始版本的demo代码里
打印下print_r(get_included_files());

define("A","456");

class demo extends Process
{
    public function runJob($worker, $index)
    {
        print_r(get_included_files());
        \swoole_set_process_name(sprintf('%s-worker-%d', 'test',$index));
        include 'job.php';
        $job=new job();
        $job->do($this);
    }
}
得到
Array
(
    [0] => /www/process/vendor/hkui/process_manager/demo.php
    [1] => /www/process/vendor/autoload.php
    [2] => /www/process/vendor/composer/autoload_real.php
    [3] => /www/process/vendor/composer/ClassLoader.php
    [4] => /www/process/vendor/composer/autoload_static.php
    [5] => /www/process/vendor/hkui/process_manager/src/Process.php
)
这时job.php并没有加载到内存里
所以每次woker重启,new job时 都会加载最新的job.php代码 ,而常量A在demo.php里定义,已经加载到了内存,所以改A必须重启master才能生效
如果把 include 'job.php'; define("A","456"); 下面,这时的get_included_files() 为
Array
(
    [0] => /www/process/vendor/hkui/process_manager/demo.php
    [1] => /www/process/vendor/autoload.php
    [2] => /www/process/vendor/composer/autoload_real.php
    [3] => /www/process/vendor/composer/ClassLoader.php
    [4] => /www/process/vendor/composer/autoload_static.php
    [5] => /www/process/vendor/hkui/process_manager/job.php
    [6] => /www/process/vendor/hkui/process_manager/src/Process.php
)
修改job内容 worker重启后new Job 不再加载job.php,而是从父进程master继承 所以不会生效,必须重启父进程master