exit(); // 等待子进程退出 $this->waitWorkersExit(); // 动态扩容 $this->workerChecked(); // 重启进程 $this->reload(); // 统计信息 $this->showStatus(); } /** * 进程退出 * * @time 2020年07月21日 * @return void */ protected function exit() { Process::signal(SIGTERM, function ($signal) { foreach ($this->workerIds as $pid => $v) { if (isset($this->workerIds[$pid])) { unset($this->workerIds[$pid]); } Process::kill($pid, SIGTERM); } Process::kill(self::getMasterPid(), SIGKILL); }); Process::signal(SIGINT, function ($signal) { foreach ($this->workerIds as $pid => $v) { if (isset($this->workerIds[$pid])) { unset($this->workerIds[$pid]); } Process::kill($pid, SIGKILL); } Process::kill(self::getMasterPid(), SIGKILL); }); } /** * 子进程退出 * * @time 2020年07月21日 * @return void */ protected function waitWorkersExit() { Process::signal(SIGCHLD, function ($signal) { }); } /** * 进程检测 * * @time 2020年07月21日 * @return void */ protected function workerChecked() { Process::signal(SIGALRM, function ($signal) { $process = new Process(function (Process $process) { $crontabs = Crontab::where('status', Crontab::ENABLE) ->where('tactics', '<>', Crontab::EXECUTE_FORBIDDEN) ->select()->toArray(); // 任务 foreach ($crontabs as $crontab) { $can = date('Y-m-d H:i', CronExpression::factory(trim($crontab['cron'])) ->getNextRunDate(date('Y-m-d H:i:s'), 0 , true) ->getTimestamp()) == date('Y-m-d H:i', time()); if ($can) { // 如果任务只执行一次 之后禁用该任务 if ($crontab['tactics'] === Crontab::EXECUTE_ONCE) { Crontab::where('id', $crontab['id'])->update([ 'status' => Crontab::DISABLE, ]); } $redis = $this->getRedisHandle(); $redis->lpush($this->crontabQueueName, json_encode([ 'id' => $crontab['id'], 'task' => $crontab['task'], ])); } } $process->exit(); }); $process->start(); Process::alarm($this->interval); }); } /** * 重启 * * @time 2020年07月21日 * @return void */ protected function reload() { Process::signal(SIGUSR1, function ($signal) { $this->worker_start_at = 0; foreach ($this->workerIds as $pid => $v) { Process::kill($pid, SIGTERM); } }, false); } /** * 预留信号 * * @time 2020年07月21日 * @return void */ protected function showStatus() { Process::signal(SIGUSR2, function ($signal) { $this->setWorkerStatus($this->name . ' master'); foreach ($this->workerIds as $pid => $v) { Process::kill($pid, SIGUSR2); } }); } }