• 分析params_s方法


    /**
         * 解析启动模式参数
         * @param $opt
         */
        static public function params_s($opt)
        {
            //判断传入了s参数但是值,则提示错误
            if ((isset($opt["s"]) && !$opt["s"]) || (isset($opt["s"]) && !in_array($opt["s"], array("start", "stop", "restart")))) {
                Main::log_write("Please run: path/to/php main.php -s [start|stop|restart]");
            }
    
            if (isset($opt["s"]) && in_array($opt["s"], array("start", "stop", "restart"))) {
                switch ($opt["s"]) {
                    case "start":
                        Crontab::start();
                        break;
                    case "stop":
                        Crontab::stop();
                        break;
                    case "restart":
                        Crontab::restart();
                        break;
                }
            }
        }
    

     这里我们先分析Crontab::start()

      从这个意思我们应该知道这应该是进程启动的方法

      因为crontab自己注册了引入方法,所以方法在include/Crontab.class.php中

    /**
         * 启动
         */
        static public function start()
        {
            if (file_exists(self::$pid_file)) {
                die("Pid文件已存在!
    ");
            }
            self::daemon();
            self::set_process_name();
            self::run();
            Main::log_write("启动成功");
        }
    

      先检查pid文件是否存在,如果存在说明进程已经启动不能再次开始

          self::daemon(); 在上一节,如果params_d($opt) 开启守护进程会执行swoole_process::daemon();//传送门:https://wiki.swoole.com/wiki/page/273.html

          self::set_process_name();//设置进程名字 这里没有支持用户自己命名,名字为:lzm_Master

      接下来执行run方法:

      

     /**
         * 运行
         */
        static protected function run()
        {
            self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);
            self::register_signal();
            if (self::$checktime) {
                $run = true;
                Main::log_write("正在启动...");
                while ($run) {
                    $s = date("s");
                    if ($s == 0) {
    
                        Crontab::load_config();
                        self::register_timer();
                        $run = false;
                    } else {
                        Main::log_write("启动倒计时 " . (60 - $s) . " 秒");
                        sleep(1);
                    }
                }
            } else {
                self::load_config();
                self::register_timer();
            }
            self::get_pid();
            self::write_pid();
            //开启worker
            if (self::$worker) {
                (new Worker())->loadWorker();
            }
        }
    

      106行:self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);//这里我们就分析LoadTasksByFile,这里放到下一讲

      107行:self::register_signal();//注册信号,用来处理进程退出

           如果在客户端进行ctrl+c退出的话,会发送SIGINT信号,但是这里没做处理,那么请不要在客户端直接ctrl+c退出程序,不然的话下次就需要执行重启命令了,因为不退出

      如果受到退出信号SIGTERM就会直接调用exit2p:删除掉pid文件然后直接exit退出

           还需要处理当子进程退出,为了不让程序变成僵尸进程需要进行wait处理

      这里是先判断是否在tasklist中pid是否存在,如果存在这个任务,则直接将子进程关闭,如果这个任务还有unique_list值(这里是任务里的排他数量的意思)会进行自减,杀死后扣除1,如果在load_config中会继续往taskTabel插入任务,争用这个unique字段
           如果是工作进程,那么复制一份work进程

      至于SIGUSR1信号,这里本来是应该是重新加载配置文件的,不知道为什么这里没有加上实现

    /**
         * 注册信号
         */
        static private function register_signal()
        {
            swoole_process::signal(SIGTERM, function ($signo) {
                self::exit2p("收到退出信号,退出主进程");
            });
            swoole_process::signal(SIGCHLD, function ($signo) {
                while ($ret = swoole_process::wait(false)) {
                    $pid = $ret['pid'];
                    if (isset(self::$task_list[$pid])) {
                        $task = self::$task_list[$pid];
                        if ($task["type"] == "crontab") {
                            $end = microtime(true);
                            $start = $task["start"];
                            $id = $task["id"];
                            Main::log_write("{$id} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
                            $task["process"]->close();//关闭进程
                            unset(self::$task_list[$pid]);
                            if (isset(self::$unique_list[$id]) && self::$unique_list[$id] > 0) {
                                self::$unique_list[$id]--;
                            }
                        }
                        if ($task["type"] == "worker") {
                            $end = microtime(true);
                            $start = $task["start"];
                            $classname = $task["classname"];
                            Main::log_write("{$classname}_{$task["number"]} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
                            $task["process"]->close();//关闭进程
                            (new Worker())->create_process($classname, $task["number"], $task["redis"]);
                        }
                    }
                };
            });
            swoole_process::signal(SIGUSR1, function ($signo) {
                //TODO something
            });
    
        }
    

      这些都执行后,会执行Crontab::load_config();

          该方法会读取到我们配置文件的读取路径中的数据,在main.php里面params_c方法会默认从ROOT_PATH . "config/crontab.php"中获取

      Crontab.class.php:line162->ParseCrontab::parse($task["rule"], $time);//这里是解析定时任务的规则返回值是每个任务的下次执行的间隔(秒级),类似linux自带的crontab的规则,这个放到后面讲解

      TickTable::set_task($ret, array_merge($task, array("id" => $id)));//这里会将读取到任务的规则写到ticktable里面
      self::register_timer();//这里才是任务调度的关键,每隔1分钟会将到下一分钟需要执行的任务插入到ticktable里面,然后每隔1s钟执行task

    下一讲:do_something方法
  • 相关阅读:
    二次识别
    IPC
    HW
    数据库异常:SQL Error: 0, SQLState: S0022
    mysql 分页查询
    [Err] 1248
    名句摘抄
    理智向左 疯狂向右
    kindle怎么导入电子书
    设置 myeclipse 编码格式
  • 原文地址:https://www.cnblogs.com/gavinjunftd/p/8080268.html
Copyright © 2020-2023  润新知