PHP PCNTL多进程编程
admin
2023-07-04 09:44:16
0

PHP中的PCNTL可以实现多进程编程,由于项目场景需要,试用了一下,感触颇多,也长了不少见识,就此对遇到的问题小做一个总结,以备不时之需。


问题一:fork泛滥

我想在一个父进程中起10个子程来完成我的工作,代码如下:

for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        Api::refreshCache();        
    }
}

由于Api::refreshCache逻辑中有数据库操作,代码一执行,就把DB搞死了,报了N多个too many connections。我以为是DB原本就抽风了,检查DB,正常。

最终发现,这一段代码fork的可不是10个子进程,而是

20 + 21 + 22+ 23 + 24 + ... + 29 = 210-1 = 1023 个子进程。

恐怖了吧?这是因为子进程又fork子进程,并且子进程不共享父进程$i变量更新的值,由此导致数量成指数关系增长。

为了避免这个问题,代码修改如下:

for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        Api::refreshCache(); 
        exit; //子进程逻辑执行完后,马上退出,以免往下走再fork子进程,不好控制     
    }
}

只要在子进程逻辑执行完后,加一个exit,一切都在撑握中了。这样,只有一个父进程,父进程后续对子进程的管理也会清晰很多。


问题二:单例模式下DB连接被虐

/*
 * 前面或远或近的地方,已经有一个$db = &MySql::getInstance();了
 */
for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        $db = &MySql::getInstance();
        $sql = "XXX";
        $result = $db->getAll($sql);
        exit;
    }
}

这段代码,十有八九都会报mysql has gone away.或者其它一些数据fetch方面的错误。究其原因,是因为各个子进程创建时,就已经继承了父进程一份完全一样的拷贝。对象可以拷贝,但是已创建的连接可不能拷贝成多个,由此产生的结果,就是各个进程都使用同一个mysql连接,各干各的事,最终产生莫名其妙的冲突。

解决办法:

我们显然不可能完全保证在fork进程之前,父进程不会创建mysql连接实例,因此,解决方案只能靠子进程本身了。可以想象,我们只需要在子进程中获取的实例只与当前进程相关,这个问题就不存在了。解决办法就是稍微改造一下mysql类实例化的静态方式,与当前进程ID绑定。

public static function &getInstance() {
    static $instances = array();
    $key = getmypid(); //获取当前进程ID
    if(empty($instances[$key])) {
        //实例化mysql类动作
        $classname = __CLASS__;
        $instances[$key] = new $classname();
    }
    return $instances[$key];
}


总结:子进程创建时,拷贝了父进程当时拥有的所有资源,虽说后面对资源的修改互不影响,但DB连接却还是同一个,造成运行混乱。

相关内容

热门资讯

玄戒技术取得分频电路专利,实现... 国家知识产权局信息显示,北京玄戒技术有限公司取得一项名为“分频电路、分频器、射频芯片和电子设备”的专...
为什么今年香会基调明显变了 5月29日—31日在新加坡举行的第23届香格里拉对话会(简称“香会”),见证着元首引领下大国关系继续...
成本几毛钱、假驱蚊液香精兑水,... 入夏升温,蚊虫进入活跃期,驱蚊防护成为民生刚需,《财经调查》持续接到消费者投诉,他们买到的多款网红驱...
越来越多80后90后,正在丧失... 六一儿童节到来之际,朋友圈里开始出现一种熟悉的热闹。有人晒出零食礼包,有人半开玩笑地向伴侣讨礼物,还...
洋保电子取得用于低温环境的电气... 国家知识产权局信息显示,洋保电子(太仓)有限公司取得一项名为“一种用于低温环境的电气柜”的专利,授权...
中日韩飞手争霸宁波!2026无... 潮新闻客户端 记者 陈冲 通讯员 朱凝 5月31日,2026小遛·无人机竞速世界杯(中国·宁波鄞州站...
谁在对台湾“温水煮青蛙”? 近一段时间以来,两岸的舆论场都非常热闹,但话题却不尽相同。先看看岛内,马英九基金会的“家变”愈演愈烈...
上海磁骋取得超级电容主动均衡电... 国家知识产权局信息显示,上海磁骋交通科技有限公司取得一项名为“一种超级电容主动均衡电路”的专利,授权...
超市运送猪肉时,一只狗跑来啃食... 5月31日,湖北孝昌的网友发布视频称,一家超市在运送猪肉时,肉从车上搬下来后,一只黑色的狗跑来啃食猪...
日本要搞两个首都? 日本媒体日前报道,日本维新会正在推进将大阪设为“副首都”的构想,定于6月中旬组建一个专门小组。对此,...