/**
* 启动守护进程
*/
public function runAction() {
log_message('ERROR', 'daemon/run' . ' | action: restart', 'daemon-');
while (true) {
$this->fork_process();
}
exit;
}
/**
* 创建子进程
*/
private function fork_process() {
$ppid = getmypid();
$pid = pcntl_fork();
if ($pid == 0) {//子进程
$pid = posix_getpid();
//echo "* Process {$pid} was created \n\n";
$this->mq_process();
exit;
} else {//主进程
$pid = pcntl_wait($status, WUNTRACED); //取得子进程结束状态
if (pcntl_wifexited($status)) {
//echo "\n\n* Sub process: {$pid} exited with {$status}";
//log_message('INFO', 'daemon/run succ' . '|status:' . $status . '|pid:' . $ppid . '|childpid:' . $pid );
} else {
//log_message('ERROR', 'daemon/run fail' . '|status:' . $status . '|pid:' . $ppid . '|childpid:' . $pid, 'daemon-');
}
}
}
/**
* 业务任务队列处理
*/
private function mq_process() {
$data_pop = $this->masterRedis->rPop($this->redis_list_key);
$data = json_decode($data_pop, 1);
if (!$data) {
return FALSE;
}
$worker = '_task_' . $data['worker'];
$class_name = isset($data['class']) ? $data['class'] : 'Model';
$params = $data['params'];
$class = new $class_name();
$class->$worker($params);
return TRUE;
}
$forkNums = 20; //开启的进程数
for($i=0;$i<$forkNums;$i++){
$pid = pcntl_fork(); //创建子进程
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
//如果不需要阻塞进程,而又想得到子进程的退出状态,则可以注释掉pcntl_wait($status)语句,或写成:
pcntl_wait($status,WNOHANG); //等待子进程中断,防止子进程成为僵尸进程。
} else {
//这里写子进程执行的逻辑
//在子进程中的变量,使用完之后,务必记得unset()注销变量,否则造成内存溢出
//子进程执行完毕之后,需要exit(0)退出程序,否则子进程无法退出,造成僵尸进程,占用系统资源。
//这里写耗时任务
//unset($data);
exit(0);
}
}
访客评论