教你一招如何使用 php 父子进程坑人

如今项目中大多都会使用MQ(消息队列)用来解耦和提高服务稳定性,而后都会面临一个问题,就是消息积压,解决这个问题除了提高处理消息的速度之外,另外就是多开些消费者进程,并发的消费数据。php

若是是其余语言能够多开些线程或协程消费数据,可是这些东西,在 php 里并无很好地支持,因此你们多采用多进程的方式来增长消费者,而后这里又有了两种方式,父子多进程和普通多进程。redis

而后这里就有了一个有趣的坑人方法,小小一技就能把人坑的想打你,那就是使用父子进程。架构

这是 php 使用父子进程的一个伪代码并发

$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
    //错误处理:建立子进程失败时返回-1.
     die('could not fork');
} else if ($pid) {
     //父进程会获得子进程号,因此这里是父进程执行的逻辑
     pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
     //子进程获得的$pid为0, 因此这里是子进程执行的逻辑。
}

那么怎么坑人呢?函数

坑人第一步,监听 signal测试

//使用ticks须要PHP 4.3.0以上版本
declare(ticks = 1);
//信号处理函数
function sig_handler($signo)
{
     switch ($signo) {
         case SIGTERM:
              // 我不想被 kill
             break;
         case SIGINT:

             // 我不想被 kill
             break;
         default:
             // 处理全部其余信号
     }
}

只须要监听两个,一个是监听的 ctrl+c 的 SIGINT ,另一个是 kill 的默认 signal (不带任何参数就是使用的这个) SIGTERM,通常人都是用这里俩方法 kill 进程,只要监听这俩信号不让进程退出,而后其余人想要像重启进程产生的第一个想法就是 kill -9,kill -9 子进程不会被干掉,赞,这样就进了咱们的套。线程

坑人第二步,修改子进程的名字,随便修改为一个相关不太相关的都行,可是不能和父进程有一样的关键词,本身能看懂就行,坑别人的同时也得给本身留条路不是,总之就是不要让别人使用 ps grep 的时候发现这是子进程,这是 php 设置进程名的一个函数code

setproctitle("myscript");

若是 php version >= 5.5.0 能够用这个协程

cli_set_process_title("myscript")

假如使用这种方式在测试环境消费MQ数据,其余人在修了代码并重启进程,就会发现本身的数据老是莫名其妙的消失,并且还找不到是谁消费的,若是是kafka或者nsq之流还能够经过新增group或channel的方式继续开发,可是若是是 redis 的 list 作 MQ ,嘿嘿……队列

坑人的同时也得防止被坑不是,咱们须要处理这种事情的时候,先找到主进程 pid ,而后使用这个命令

ps --ppid 父进程的pid

我懂得,你确定想喷我,你这人这么怎么缺德,呵呵呵,我就是被人这么坑了一会,才这么印象深入,难受。

更多架构、PHP、GO相关踩坑实践技巧请关注个人公众号:PHP架构师

相关文章
相关标签/搜索