WorkerMan::Worker类解析(2)

    // 解析命令.
    protected static function parseCommand()
    {
        global $argv;
        // Check argv;
        $start_file = $argv[0];
        $available_commands = array(
            'start', // 启动.
            'stop', // 停止.
            'restart', // 重启:先stop->后start.
            'reload', // 重新加载配置(相当于子进程慢慢重启,保证客户端链接不挂)
            'status', // 查看当前服务运行状态.
            'connections', // 查看客户端连接情况.
        );
        // 必须要输入命令:php start.php start|restart|stop...
        $usage = "Usage: php yourfile.php {" . implode('|', $available_commands) . "} [-d]\n";
        if (!isset($argv[1]) || !in_array($argv[1], $available_commands)) {
            exit($usage);
        }

        // 获取命令.
        $command  = trim($argv[1]);
        // 参数:-d守护进程,-g平滑的停止worker.
        $command2 = isset($argv[2]) ? $argv[2] : '';

        // Start command.
        $mode = '';
        if ($command === 'start') {
            // 守护进程模式.
            if ($command2 === '-d' || Worker::$daemonize) {
                $mode = 'in DAEMON mode';
            } else {
                // 调试模式.
                $mode = 'in DEBUG mode';
            }
        }
        self::log("Workerman[$start_file] $command $mode");

        // 获取workerman服务的主进程id.
        $master_pid      = is_file(self::$pidFile) ? file_get_contents(self::$pidFile) : 0;
        // posix_kill($master_pid, 0)判断主进程是否还存活.
        $master_is_alive = $master_pid && @posix_kill($master_pid, 0) && posix_getpid() != $master_pid;
        if ($master_is_alive) {
            // 如果主进程存活,输入的是启动命令则退出本次命令操作.
            if ($command === 'start') {
                self::log("Workerman[$start_file] already running");
                exit;
            }
        } elseif ($command !== 'start' && $command !== 'restart') {
            // 如果主进程不存在,输入的命令不是start和restart则退出本次操作.
            self::log("Workerman[$start_file] not run");
            exit;
        }

        // execute command.
        switch ($command) {
            case 'start':
                if ($command2 === '-d') {
                    Worker::$daemonize = true;
                }
                break;
            case 'status':
                // 查看服务运行状态.
                while (1) {
                    if (is_file(self::$_statisticsFile)) {
                        // 统计文件存在则进行删除.
                        @unlink(self::$_statisticsFile);
                    }
                    // 给主进程发送SIGUSR2信号,然后主进程给所有的worker子进程发送SIGUSR2信号,上报自己的信息.
                    posix_kill($master_pid, SIGUSR2);
                    // Sleep 1 second.
                    sleep(1);
                    // 清空终端(相当于执行了ctrl+l).
                    if ($command2 === '-d') {
                        echo "\33[H\33[2J\33(B\33[m";
                    }
                    // 将主进程和各个业务状态格式化输出.
                    echo self::formatStatusData();
                    // 如果没有带-d参数获取一次就退出,带了-d参数相当于每秒获取一次.
                    if ($command2 !== '-d') {
                        exit(0);
                    }
                    echo "\nPress Ctrl+C to quit.\n\n";
                }
                exit(0);
            case 'connections':
                // 查看客户端连接情况.
                if (is_file(self::$_statisticsFile)) {
                    @unlink(self::$_statisticsFile);
                }
                // 主进程发送SIGIO信号给各个子进程.
                posix_kill($master_pid, SIGIO);
                // 等待各个子进程上报数据.
                usleep(500000);
                // 输出统计信息文件.
                @readfile(self::$_statisticsFile);
                exit(0);
            // 不管是restart还是stop操作,都是要先将老的worker进程杀死.
            // restart = stop + start;
            case 'restart':
            case 'stop':
                if ($command2 === '-g') {
                    self::$_gracefulStop = true;
                    $sig = SIGTERM;
                    self::log("Workerman[$start_file] is gracefully stoping ...");
                } else {
                    self::$_gracefulStop = false;
                    $sig = SIGINT;
                    self::log("Workerman[$start_file] is stoping ...");
                }
                // 给主进程发送停止信号.
                $master_pid && posix_kill($master_pid, $sig);
                // Timeout.
                $timeout    = 5;
                $start_time = time();
                // Check master process is still alive?
                while (1) {
                    // 判断旧的主进程是否还存活.
                    $master_is_alive = $master_pid && posix_kill($master_pid, 0);
                    if ($master_is_alive) {
                        // 停止操作超时,本次操作结束.
                        if (!self::$_gracefulStop && time() - $start_time >= $timeout) {
                            self::log("Workerman[$start_file] stop fail");
                            exit;
                        }
                        // 等待主进程结束.
                        usleep(10000);
                        continue;
                    }
                    // Stop success.
                    self::log("Workerman[$start_file] stop success");
                    // 如果是停止命令,杀死运行的worker以后,本次执行也结束.
                    if ($command === 'stop') {
                        exit(0);
                    }
                    // 如果是重启命令,那么是杀死老的worker,程序往下执行,当前进程变主进程.
                    if ($command2 === '-d') {
                        Worker::$daemonize = true;
                    }
                    break;
                }
                break;
            case 'reload':
                if($command2 === '-g'){
                    $sig = SIGQUIT;
                }else{
                    $sig = SIGUSR1;
                }
                // worker加载新的配置文件,当前进程结束.
                posix_kill($master_pid, $sig);
                exit;
            default :
                exit($usage);
        }
    }

首先进行的命令检查.

根据不同的命令执行不同的操作.
1. start // 启动.
    php file.php start
    php file.php start -d // 守护进程方式启动.
    核心代码:
    $master_pid && @posix_kill($master_pid, 0) && posix_getpid() != $master_pid
    // 判断主进程是否存活.

2. stop // 停止.
    php file.php stop
    php file.php stop -g // 平滑关闭.
    核心代码:
    // 给主进程发送停止信号.
    $master_pid && posix_kill($master_pid, $sig);
    // 判断旧的主进程是否还存活.
    $master_is_alive = $master_pid && posix_kill($master_pid, 0);

3. restart // 重启:先stop->后start.
    php file.php restart
    php file.php restart -d
    php file.php restart -g

4. reload // 重新加载配置(相当于子进程慢慢重启,保证客户端链接不挂)
    php file.php reload
    php file.php reload -g
    核心代码:
    // worker加载新的配置文件,当前进程结束.
    posix_kill($master_pid, $sig);

5. status // 查看当前服务运行状态.
    php file.php status
    php file.php status -d // 每秒获取一次.
    核心代码:
    // 给主进程发送SIGUSR2信号,然后主进程给所有的worker子进程发送SIGUSR2信号,上报自己的信息.
    posix_kill($master_pid, SIGUSR2);

6. connections // 查看客户端连接情况.
    php file.php connections
    核心代码:
    // 主进程发送SIGIO信号给各个子进程.
    posix_kill($master_pid, SIGIO);

重点:命令解析方法的核心在于外部传入命令,通过保存的主进程id,向运行的主进程发送信号,从而达到外部控制运行中的worker进程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值