前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP使用守护进程处理队列

PHP使用守护进程处理队列

作者头像
用户3094376
发布2018-09-12 11:05:51
1.1K0
发布2018-09-12 11:05:51
举报
文章被收录于专栏:gaoqin31gaoqin31

一.概述

  项目是棋牌,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 if($daemonNum > $wokerNum){//进程数过多自行kill
    $pidStr = `ps -ef | grep "gamelog.php" | grep -v grep | awk '$3 == 1 {print $2}'`;
    $aPid = explode(PHP_EOL, $pidStr);
    $wokerNum = max($wokerNum, PROC_MIN);//最少保留PROC_MIN个守护进程
    $killNum = $daemonNum - $wokerNum;
    foreach($aPid as $pid){
        $pid = (int) $pid;
        if($pid <= 0){
            continue;
        }
        if(posix_kill($pid, SIGKILL)){
            if(--$killNum <= 0){
                break;
            }
        }
    }
}

php执行shell命令除了system(),exec(),还可以使用``。 posix_setsid()函数php手册里只有一句说明 Make the current process a session leader posix_setsid对应的unix系统函数是setsid(),当进程调用setsid会产生一个新的会话,而且这个进程将不受终端控制 之前进程有终端控制也会被解除,所以我们在命令行启动gamelog.php,然后关掉终端不会杀掉gamelog.php产生的子进程

三.改进后的效果   1.改进后server写redis队列远比通过http协议请求php快,极大减少了server等待牌局处理的时间。   2.php-fpm不用处理牌局的请求,改由后台进程处理,释放了php-fpm。

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3mj93mrrhoqos

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档