• PHP 异步使用swoole的可行性测试


      PHP的异步、并行、高性能网络通信引擎swoole框架,在一开始我就比较注意,原因无他,php在swoole未出的情况下在多线程调度上确实算得上没有较好的解决方案。

      我以系统的注册流程举例,在比较复杂的系统中,用户创建,需要同时做出很多相应的其他的操作,比如关联其他的业务表,发送邮件等操作是比较耗时的,但是其实又和登陆信息的注册毫无关系,一般情况我们会丢到队列服务中去。然后通过使用定时任务去处理用户创建后的其他异步操作。那既然前景和旧的解决方案已经提出来,那么使用swoole能做得更好吗?

      这里我使用的是swoole的TCP服务器作为邮件异步服务器开启task来作为异步操作,然后web端调用swoole的TCP客户端发送后不等待recv接收直接关闭。下面贴出我的执行代码

      TCP的服务器

      

    <?php
    
    /**
     * Created by PhpStorm.
     * User: xujun
     * Date: 2017/7/28
     * Time: 22:26
     */
    class TcpService
    {
        public function run(){
            $serv = new swoole_server("127.0.0.1", 9502);
    
            //设置异步任务的工作进程数量
            $serv->set(array('task_worker_num' => 4));
    
            $serv->on('receive', function($serv, $fd, $from_id, $data) {
                //投递异步任务
                $task_id = $serv->task($data);
                echo "异步任务id=$task_id
    ";
            });
    
    //处理异步任务
            $serv->on('task', function ($serv, $task_id, $from_id, $data) {
                echo "异步任务[id=$task_id]".PHP_EOL;
                //返回任务执行的结果
                //为了测试时间的延时性这里我做了大数组的特性
                try{
                    //会内存超出
                    $arr = array_fill(0,100000,0);
                    foreach ($arr as $v){
                        //echo $v;
                    }
                    foreach ($arr as $v){
                        //echo $v;
                    }
                    $num = 0;
                    while(true){
                        if($num>2147483647){
                            break;
                        }
                        $num++;
                    }
                }catch(Exception $e){
                    $e->getMessage();
                }
    
                $serv->finish("[".date('Y-m-d H:i:s')."]{$data}邮箱已经发送");
            });
    
    //处理异步任务的结果
            $serv->on('finish', function ($serv, $task_id, $data) {
                echo "异步任务[$task_id] 完成: $data".PHP_EOL;
            });
    
            $serv->start();
        }
    }
    
    $a = new TcpService();
    $a->run();
    

      下面是web客户端的脚本

      

    <?php
    //处理管道
    class Cross{
        public function process(array $stages, $payload)
        {
            foreach ($stages as $stage) {
                $payload = call_user_func($stage, $payload);
            }
            return $payload;
        }
    }
    //管道
    class Pipeline
    {
    
        private $stages = [];
    
        public function __construct(array $stages = [])
        {
            foreach ($stages as $stage) {
                if (false === is_callable($stage)) {
                    throw new Exception('All stages should be callable.');
                }
            }
            $this->stages = $stages;
            $this->processor =new Cross;
        }
        /**
         * @inheritdoc
         */
        public function pipe(callable $stage)
        {
            $this->stages[] = $stage;
            return $this;
        }
        /**
         * Process the payload.
         *
         * @param $payload
         *
         * @return mixed
         */
        public function process($payload)
        {
            return $this->processor->process($this->stages, $payload);
        }
    
    }
    
    $pie = new Pipeline();
    $pie->pipe(function($payload){
        echo '系统用户'.$payload.'数据验证成功<br>';
        return $payload;
    })->pipe(function($payload){
        echo '系统用户数据生成<br>';
        return $payload;
    })->pipe(function($payload){
        echo '异步开始发送验证邮件<br>';
        //创建swoole客户端
        try{
            $client = new swoole_client(SWOOLE_SOCK_TCP);
    
    //连接到服务器
            if (!$client->connect('127.0.0.1', 9502, 0.5))
            {
                die("connect failed.");
            }
    //向服务器发送数据
            if (! $client->send("系统发送给用户{$payload}一封验证邮件"))
            {
                die("send failed.");
            }
    
            $client->close();
    
    
    
    
        }catch (Exception $e){
            echo $e->getMessage();
        }
        return $payload;
    })->pipe(function($payload){
        echo date('Y-m-d H:i:s').'系统成功创建用户<br>';
    });
    $pie->process('我是09');
    

      测试顺序是,先开启tcp服务器,然后访问web脚本

      执行结果

      web脚本

      

      TCP服务器的处理值

      

       从结果上来说,验证邮件发送并没有阻塞到web脚本,也就是满足我们的异步要求。

  • 相关阅读:
    从helloworld回顾程序的编译过程之二
    笔试题知识点记录
    jQuery面试题与答案
    hdu2586(How far away ?)
    解析PHP跳出循环的方法以及continue、break、exit的区别介绍
    如何查看任何一下网站的全部二级域名?
    urlencode()与urldecode()
    基于 LaravelAdmin 在十分钟内搭建起功能齐全的后台模板
    第一种方式:cookie的优化与购物车实例
    右键菜单的响应问题
  • 原文地址:https://www.cnblogs.com/gavinjunftd/p/7253258.html
Copyright © 2020-2023  润新知