时间:2023-05-26 19:27:02 | 来源:网站运营
时间:2023-05-26 19:27:02 来源:网站运营
PHP开发者该知道的多进程消费队列:<?php$i = 1;while (1) { echo "开始第[{$i}]次循环/n"; sleep(10); echo "结束第[{$i}]次循环/n"; $i++;}
当我们运行脚本之后,等到循环开始之后,给进程发送 kill {KaTeX parse error: Expected 'EOF', got '}' at position 4: pid}̲,默认发送的是编号为15的SI…i是从队列拿到的,拿到2的时候,正在处理,我们给程序发送了kill信号,和队列数据丢失一样,问题比较大,因此我要想办法解决这些问题。开始第[1]次循环结束第[1]次循环开始第[2]次循环[1] 28372 terminated php t.php
SIGINT => 平滑退出,处理完正在处理的数据再退出SIGTERM => 暴力退出,无论进程是否正在处理数据直接退出SIGUSR1 => 查看进程状态,查看进程占用内存,运行时间等信息
master进程通过信号和worker进程通讯,worker进程安装了2个信号,如下所示:SIGINT => 平滑退出SIGUSR1 => 查看worker进程自身状态
为什么worker进程只安装2个信号呢,少了个SIGTERM,因为master进程收到信号SIGTERM之后,向worker进程发送SIGKILL信号,默认强制关闭进程即可。bool pcntl_signal ( int $signo , [callback $handler [, bool $restart_syscalls = true ] )
第三个参数restart_syscalls不太好理解,找了很多资料,也没太查明白,经过试验发现,这个参数对pcntl_wait函数接收信号有影响,当设置为缺省值true的时候,发送信号,进程用pcntl_wait收不到,必须设置为false才可以,看看下面这个例子:<?php$i = 0;while ($i<5) { $pid = pcntl_fork(); $random = rand(10, 50); if ($pid == 0) { sleep($random); exit(); } echo "child {$pid} sleep {$random}/n"; $i++;}pcntl_signal(SIGINT, function($signo) { echo "Ctrl + C/n";});while (1) { $pid = pcntl_wait($status); var_dump($pid); pcntl_signal_dispatch();}
运行之后,我们对父进程发送kill -SIGINT {$pid}信号,发现pcntl_wait没有反应,等到有子进程退出的时候,发送过的SIGINT会一个个执行,比如下面结果:child 29643 sleep 48child 29644 sleep 24child 29645 sleep 37child 29646 sleep 20child 29647 sleep 31int(29643)Ctrl + CCtrl + CCtrl + CCtrl + Cint(29646)
这是运行脚本之后马上给父进程发送了四次SIGINT信号,等到一个子进程推出的时候,所有信号都会触发。pcntl_signal(SIGINT, function($signo) { echo "Ctrl + C/n";}, false);
这时候给父进程发送SIGINT信号,pcntl_wait会马上返回-1,信号对应的事件也会触发。<?phppcntl_signal(SIGINT, function($signo) { echo "Ctrl + C/n";}, false);while (true) { pcntl_signal_dispatch(); echo "123/n"; $limit = sleep(2); echo "limit sleep [{$limit}] s/n";}
运行之后,按Ctrl + C,结果如下所示:123^Climit sleep [1] sCtrl + C123limit sleep [0] s123^Climit sleep [1] sCtrl + C123^Climit sleep [2] s
protected function daemonize(){ $pid = pcntl_fork(); if (-1 == $pid) { throw new Exception("fork进程失败"); } elseif ($pid != 0) { exit(0); } if (-1 == posix_setsid()) { throw new Exception("新建立session会话失败"); } $pid = pcntl_fork(); if (-1 == $pid) { throw new Exception("fork进程失败"); } else if($pid != 0) { exit(0); } umask(0); chdir("/");}
拢共分五步:➜/dir /usr/local/bin/php DaemonMcn.php statusDaemon [DaemonMcn] 信息:-------------------------------- master进程状态 --------------------------------pid 占用内存 处理次数 开始时间 运行时间16343 0.75M -- 2018-05-15 09:42:45 0 天 0 时 3 分12 slaver-------------------------------- slaver进程状态 --------------------------------任务task-mcq:16345 0.75M 236 2018-05-15 09:42:45 0 天 0 时 3 分16346 0.75M 236 2018-05-15 09:42:45 0 天 0 时 3 分--------------------------------------------------------------------------------任务test-mcq:16348 0.75M 49 2018-05-15 09:42:45 0 天 0 时 3 分16350 0.75M 49 2018-05-15 09:42:45 0 天 0 时 3 分16358 0.75M 49 2018-05-15 09:42:45 0 天 0 时 3 分16449 0.75M 1 2018-05-15 09:46:40 0 天 0 时 0 分--------------------------------------------------------------------------------
等待worker进程将进程信息写入文件的时候,这个地方用了个比较trick的方法,每个worker进程输出一行信息,统计文件的行数,达到worker进程的行数之后表示所有worker进程都将信息写入完毕,否则,每个1s检测一次。关键词:进程,消费