资讯专栏INFORMATION COLUMN

基于Swoole的Process进程管理模块支付结果回调服务

wenzi / 2164人阅读

摘要:原先用的多线程实现的支付结果回调服务,在后期运行中出现了服务停止的问题,在学习的过程中,发现可以用的进程管理模块实现多线程的功能,并且使用定时器功能实现进程监控在子进程退出的时候进行重启。

原先用PHP的Pthread多线程实现的支付结果回调服务,在后期运行中出现了服务停止的问题,在学习swoole的过程中,发现可以用swoole的Process进程管理模块实现多线程的功能,并且使用swoole_time_tick定时器功能实现进程监控在子进程退出的时候进行重启。
1、开发环境

    Swoole版本:2.0.12

    PHP版本:7.1

    服务器版本:Ubuntu 14.04 64位

2、业务场景

    游戏APP在支付后,在支付宝,微信等回调支付结果后,将支付结果回调给游戏服务器。回调逻辑为:25 小时以内完成 8 次通知(通知的间隔频率一般是:0s,2m,10m,10m,1h,2h,6h,15h)。第一次通知在接收到结果时同时回调。所以另外7次间隔性回调由7个进程分别操作。每个进程服务运行时间不一致,当前业务时间间隔各为1s,2s,30s,30s,60s,300s,600s,600s一次

3、代码实例
use SwooleProcess;

class MyProcess
{
    public $mpid = 0; // master pid, 即当前程序的进程ID
    public $works = []; // 记录子进程的 pid
    public $maxProcessNum = 7;
    public $newIndex = 1;

    public function __construct()
    {
        try {
            swoole_set_process_name(" MyProcess : master");
            $this->mpid = posix_getpid();
            $this->run();
            $this->processWait();
        } catch (Exception $e) {
            die("Error: ". $e->getMessage());
        }
    }

    public function run()
    {
        //创建进程
        for ($i=0; $i<=$this->maxProcessNum; $i++) {
            $this->createProcess($i);
        }
    }


    public function createProcess($index = null)
    {
        if (is_null($index)) {
            $index = $this->newIndex;
            $this->newIndex++;
        }
        echo date("Y-m-d H:i:s") . "  |  createProcess index=".$index.PHP_EOL;
        $process = new swoole_process(function (swoole_process $worker) use($index) { // 子进程创建后需要执行的函数
            swoole_set_process_name(" MyProcess : worker $index");
            //根据进程启用不同时间间隔的定时器 $ms为毫秒 支付回调7次尝试 7个进程回调服务 每次回调的间隔时间不一致,实行25 小时以内完成 8 次通知(通知的间隔频率一般是:2m,10m,10m,1h,2h,6h,15h)
            switch ($index) {
                case 0;
                    $ms = 1000;
                    break;
                case 1;
                    $ms = 2000;
                    break;
                case 2;
                    $ms = 30000;
                    break;
                case 3;
                    $ms = 30000;
                    break;
                case 4;
                    $ms = 60000;
                    break;
                case 5;
                    $ms = 300000;
                    break;
                case 6;
                    $ms = 600000;
                    break;
                case 7;
                    $ms = 600000;
                    break;
            }
            //启用定时器
            $timer=swoole_timer_tick($ms,"MyProcess::deal_pay_notify", $index);

        }, false, false); // 不重定向输入输出; 不使用管道
        $pid = $process->start();
        $this->works[$index] = $pid;
        return $pid;
    }

    /*
        * 处理支付回调
        */
    function deal_pay_notify($timmerID, $params){
        echo date("Y-m-d H:i:s") . "  |  timmerID=".$timmerID." params=".$params.PHP_EOL;

        //支付结果回调操作
        //......

    }

    // 重启子进程
    public function rebootProcess($pid)
    {
        $index = array_search($pid, $this->works);
        if ($index !== false) {
            //重新创建进程
            $newPid = $this->createProcess($index);
            echo "rebootProcess: {$index}={$pid}->{$newPid} Done
";
            return;
        }
        throw new Exception("rebootProcess error: no pid {$pid}");
    }


    // 监控子进程
    public function processWait()
    {
        //定时器每秒监控
        swoole_timer_tick(1000,"MyProcess::monitor_process", "");
        /*while (1) {
            if (count($this->works)) {
                $ret = Process::wait(); // 子进程退出
                if ($ret) {
                    $this->rebootProcess($ret["pid"]);
                }
            } else {
                break;
            }
        }*/
    }

    //检测进程
    public function monitor_process($timmerID, $params){
        foreach($this->works as $pid){
            if (!Process::kill($pid, 0)) { // 0 可以用来检测进程是否存在
                $this->rebootProcess($pid); //重启进程
                echo date("Y-m-d H:i:s") . "  |  monitor_process pid=".$pid. " restart".PHP_EOL;
            }
        }
    }
}

new MyProcess();

gitee:https://gitee.com/oydm/codes/...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28404.html

相关文章

  • PHP多进程系列笔记(五)

    摘要:消息队列更常见的用途是主进程分配任务,子进程消费执行。子进程前面加了个,这是为了防止父进程还未往消息队列中加入内容直接退出。 前面几节都是讲解pcntl扩展实现的多进程程序。本节给大家介绍swoole扩展的swoole_process模块。 swoole多进程 swoole_process 是swoole提供的进程管理模块,用来替代PHP的pcntl扩展。 首先,确保安装的swoole...

    qianfeng 评论0 收藏0
  • Swoole 在 Swoft 中应用

    摘要:在中的应用官网源码解读号外号外欢迎大家我们开发组定了一个就线下聚一次的小目标上一篇源码解读反响还不错不少同学推荐再加一篇讲解一下中使用到的功能帮助大家开启的实战之旅服务器开发涉及到的相关技术领域的知识非常多不日积月累打好基础是很难真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的应用 swoft 官网: https://www.sw...

    EscapedDog 评论0 收藏0
  • Swoft 源码剖析 - Swoole和Swoft那些事(Task投递/定时任务篇)

    摘要:作为定时任务的执行者,通过每唤醒自身一次,然后把执行表遍历一次,挑选当下需要执行的任务,通过投递出去并更新该任务执行表中的状态。 作者:bromine链接:https://www.jianshu.com/p/b44...來源:简书著作权归作者所有,本文已获得作者授权转载,并对原文进行了重新的排版。Swoft Github: https://github.com/swoft-clou.....

    vvpvvp 评论0 收藏0
  • Swoole 源码分析——进程管理 Swoole_Process

    摘要:清空主进程残留的定时器与信号。设定为执行回调函数如果在回调函数中调用了异步系统,启动函数进行事件循环。因此为了区分两者,规定并不允许两者同时存在。 前言 swoole-1.7.2 增加了一个进程管理模块,用来替代 PHP 的 pcntl 扩展。 PHP自带的pcntl,存在很多不足,如 pcntl 没有提供进程间通信的功能 pcntl 不支持重定向标准输入和输出 pcntl 只...

    pepperwang 评论0 收藏0
  • swoole入门4-初识swoole

    摘要:当某种网络事件发生时,会回调用户设置的指定回调函数。承担了底层网络事件的监听及各种底层事件处理,当收到请求时,会触发事件提醒,然后将控制权转交预先注册的事件回调函数,来进行后续的处理。请求到来时创建,请求结束后销毁。 运行流程图 showImg(https://segmentfault.com/img/remote/1460000017207791);showImg(https://s...

    forsigner 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<