当前位置: 首页 > 后端技术 > PHP

PHP流程实现与管理

时间:2023-03-29 14:40:22 PHP

应用场景一些耗时任务:大数据分表后的统计信息功能批量发送短信或邮件功能其他可以分目标的任务功能(多种)所以我们需要一个定时的In-memory任务管理工具,为了保证实时性,一方面我们让它一直执行任务(适当休眠,保证cpu不100%占用),另一方面另一方面,我们实现多进程来保证任务的并发执行,当然除此之外,根据情况也可以使用线程和协程。在实现PHP流程之前,需要了解PHP的常见运行模式:CGI通用网关接口模式、FAST-CGI模式、CLI命令行模式(phpxxx.php)模块模式(作为服务器模块),以及PHP进程使用CLI命令行模式运行的基本实现,在PHP中提供了一个扩展pcntl,可以利用操作系统的fork调用来实现多进程。fork调用后执行的代码将是并行的,只能在linux下运行。$ppid=posix_getpid();//获取当前进程的PID$pid=pcntl_fork();//Createprocessswitch($pid){//Createprocesserrorcase-1:thrownewException('Forkchildprocessfailed!');休息;//子进程workercase0:$cpid=posix_getpid();cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}。");睡觉(30);出口;//此处退出,避免worker继续执行后面的代码导致的一些问题break;//主进程masterdefault:cli_set_process_title("我是父进程,我的进程id是{$ppid}。");pcntl_wait($status);//挂起父进程,等待并返回子进程的状态,防止子进程成为僵尸进程break;}运行命令行phpxxx.php后,使用psaux|grep进程看:如果没有看到,可能是中文乱码。使用psaux查看或使用ps–ajft查看层级显示进程管理——防止进程成为僵尸进程。创建进程后,如何管理子进程?使用信号,对子进程的管理一般有两种情况:当需要信号终止子进程时终止子进程;pcntl_waitpid():等待或返回fork子进程的状态,如果调用该函数时指定的子进程已经退出(俗称僵尸进程),该函数将立即返回并释放该子进程的所有系统资源,这个进程可以防止子进程变成僵尸进程,造成系统资源的浪费;孤儿进程:父进程挂掉,子进程由pid=1(wait/waitpid)的init进程接管,直到子进程自身的生命周期结束,被系统回收资源,父进程取相关恢复操作。僵尸进程:子进程退出,父进程没有通过wait/waitpid获取子进程的状态,子进程占用的进程号等描述资源依然存在,造成危害:比如进程号受限,进程号不能释放,所以可能没有以后可用的进程号**在父进程中使用:pcntl_wait或pcntl_waitpid目的是防止worker成为僵尸进程:使用pcntl_wait()后,子进程死后,父进程也会停止**最后,我们通过下图简单总结描述一下这个多进程(1-1)实现过程:进程管理-进程间通信队列:如Redis,推荐socket:推荐管道:实现复杂,且管道(pipe)以文件形式存在,存在硬盘IO性能瓶颈信号:携带的信息量小,不易管理进程管理nt-切换到一个daemon进程&实现phpdeadloop.php&实际使用了一个耗时10S的多进程任务,执行两次,一共耗时20S,同时开启2个进程,只用了10S,如下:php:index.php(进程启动脚本):echo'Starttime:'.date('H:i:s',time())."\n";$cmds=[['./job.php',0,50000],//执行脚本并传递参数['./job.php',50000,100000]];for($i=0;$i<2;$i++){$ppid=posix_getpid();//获取当前进程PID$pid=pcntl_fork();//创建进程开关($pid){//创建进程错误案例-1:thrownewException('forkchildprocessfailed!');休息;//子进程workercase0:$cpid=posix_getpid();cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}。");//执行业务脚本pcntl_exec('/usr/local/php/bin/php',$cmds[$i]);出口;//此处退出,避免worker继续执行后面的代码导致的一些问题break;}}//等待子进程结束while(pcntl_waitpid(0,$status)!=-1){$status=pcntl_wexitstatus($status);echo'子进程的结束时间:'.date('H:i:s',time())."\n";}运行phpindex.php后:示例达到预期效果