PHP使用守护进程处理队列

 一.概述

  项目是棋牌,web架构是典型的lnmp,server产生的牌局通过http协议请求webserver,由php分析并持久化到mysql,中间参杂了很多业务逻辑,整个流程耗时平均接近2s。
这种方式存在以下2个问题
1.整个流程是同步的,server会一直等待php响应,一旦server处理不慎,会造成server阻塞,玩家无法玩牌。
2.如果牌局数量较多,会占用较多的php-fpm进程,可能造成php-fpm无法处理其他业务。

 

二.改进方式

  后面改由server把牌局数据写到redis队列里,php使用守护进程处理redis队列。
cron每5分钟运行gamelog.php,gamelog检测牌局队列数量,根据队列的数量动态fork对应的子进程处理牌局业务,当子进程数量有多余的空闲进程,gamelog.php
会杀掉多余的进程,这种方式参考了php-fpm的dynamic模式,具体实现如下:

复制代码
define('LEN', 50);//单进程处理牌局队列长度define('PROC_MIN', 2);//最小进程数define('PROC_MAX', 5);//最大进程数ini_set('memory_limit', '128M'); umask(002); set_time_limit(0);//cli模式非必须$daemonNum = (int) `ps -ef | grep "gamelog.php" | grep -v grep | awk '$3 == 1 {print $2}' | wc -l`;//当前守护进程数$appGameLog = app::gamelog(); $appRedis = app::redis('log'); $key = akey::gamelog(); $len = $appRedis->lSize($key); $wokerNum = ceil($len / LEN);//需要的进程数($wokerNum < PROC_MIN) && ($wokerNum = PROC_MIN); if($daemonNum < $wokerNum){//守护进程数小于需要开启的进程数    $procNum = $wokerNum - $daemonNum;     $procNum = min($procNum, PROC_MAX);     $procNum = max($procNum, PROC_MIN);          for($p = 1; $p <= $procNum; $p++){         $pid = pcntl_fork();         if($pid == 0){             posix_setsid();             while(true){                 $data = $appRedis->rPop($key);                 //此处处理业务            }             exit;         }else if($pid > 0){                      }else{             exit("fork error");         }     } }else
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信