zoukankan      html  css  js  c++  java
  • PHP异步:fsockopen及swoole异步

    一、同步与异步的区别:

      1、同步模式:后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的.

      2、异步模式:则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。 "异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,就现在来说应该没有什么后台服务器还是同步操作了

    举一个场景:在用户抢票的时候,并不希望用户排队去连接数据库进行查询、判断、插入,完成之后再返回用户结果。其实我们并不需要用户等那么久的时间,用户提交之后,直接告诉他已经抢票成功了就可以了,至于各种操作,交给后台去处理就好。当然,这种情况我们现在都用消息列表来处理,把每一个用户提交的请求存在一个消息列队中,告诉用户已经搞定了,用户愉快的关掉页面之后,实际上后台还在一个一个从消息列队中取出请求进行操作。我们这篇文章则是通过一种异类的手法,实现操作在后台运行,无需用户等待。

    二、fsockopen异步

      对于php来说最大缺点就是无法实现多线程管理,其程序的执行都是从头到尾,按照逻辑一路执行下来,不可能出现分支,

      1、创建需要操作耗时方法

     //循环操作1w次数据库
        public function test(){
            $i=input('id')?input('id'):1;
            while ( $i<= 10000) {
                echo $i;
                echo '<br/>';
                $data = ['title' => $i.'-'.date('Y-m-d H:i:s'), 'num' => $i];
                Db::name('input')->insert($data);
                $i++;
            }
            echo '完成';
        }
    

      2、我们创建了一个基于fsockopen的函数,这个函数中利用fsockopen去访问url,但是在访问时,并不要求获取url显示的内容,而是仅仅发出访问请求,请求到达后马上关闭这个访问。这样做的好处就是无需再等待被访问的url是否返回了可靠的信息,节约了时间,这段代码的执行时间在0.1-0.2秒之间,对于普通访客而言,几乎察觉不到。因此,在使用时,仅需要调用这个函数和对应的url即可。不过,这里并没有提供数据传输的部分,如何传输数据,其实只需要在$header中增加post的内容即可。

      

    	/**
    	 * @生生 2018/12/24 19:25:06
         * [asynchronous PHP异步执行任务]
         * @param  string $url       执行任务的url地址
         * @param  array  $post_data 需要post提交的数据POST
         * @param  array  $cookie    cookie数据用于登录等的设置(此处内部调用,无需鉴权)
         * @return boole
         */
    public function asynchronous($url,$post_data = array())
        {
        	$url_array = parse_url($url);
        	dump($url_array);
        	//用fsockopen()尝试连接  
    		$fp = fsockopen($url_array['host'], 80, $errno, $errstr, 30);
    		if (!$fp) {
    		    echo "$errstr ($errno)<br />
    ";
    		} else {
    			//建立成功后,向服务器写入数据  
    			$getPath = isset($url_array['path']) ? $url_array['path'] : '/';
    		    $out = "GET /".$getPath."/ HTTP/1.1
    ";
    		    $out .= "Host:".$url_array['host']."
    ";
    		    $out .= "Connection: Close
    
    ";
    		 
    		    fwrite($fp, $out);
    		    /*忽略执行结果
    		    while (!feof($fp)) {
    		        echo fgets($fp, 128);
    		    }*/
    		    //关闭链接
    		    fclose($fp);
    		}
        }
    

      3、创建调起方法

        //调用方法
    	function yibu(){
    
    		/**
    		 *	异步方法
    		 *	参数:(string)要执行的方法url,(array)传入参数
    		 */
    		$this->asynchronous('http://119.23.33.37/index.php/admin/index/test',['1'=>'haha']);
    		//直接返回结果
    		echo '操作成功';
    	}
    

      4、浏览器访问调起方法(直接返回操作结果,大量循环后台慢慢执行)

    三、swoole异步操作

     1、创建异步服务器

    <?php
    //include '../application/admin/controller/SwooleAsynchronous.php'; 
    /**
     * @生生 2018.1.1
     * 创建异步服务器
     */
    $ser = new swoole_server('0.0.0.0',9506);
    //设置进程数
    $ser->set(array('task_worker_num'=>4));
    
    //当有数据进来的时候
    $ser->on('receive',function($ser,$fd,$from_id,$data){
    	//投递异步任务
    	$task_id = $ser->task($data);
        echo "Dispath AsyncTask: id=$task_id
    ";
    });
    
    /**
     * @处理异步任务
     * 调用$serv->task()后,程序立即返回,继续向下执行代码
     */
    $ser->on('task',function($ser,$task_id,$from_id,$data){
    	echo "这个是:$task_id".'-'.$data.PHP_EOL;
    	//call_user_func('SwooleAsynchronous::huidiao', $value);
        //返回任务执行的结果
        $ser->finish("任务完成");
    });
    
    /**
     * @处理异步任务的结果
     * finish操作是可选的,也可以不返回任何结果
     */
    $ser->on('finish', function ($ser,$task_id,$data) {
    	sleep(5);
        echo "数据是:$data".PHP_EOL;
    });
    
    //开启
    $ser->start();
    

    2、执行异步(执行方法前要引入swoole_client这个类)

    public function index(){
              //异步处理方法 $url = url('index/swooletest/test','','','119.23.33.37'); $params=[ ['id'=>1,'url'=>$url], ];//接口数据 $msg = json_encode($params); $client = new swoole_client(SWOOLE_SOCK_TCP); //连接到服务器 if (!$client->connect('127.0.0.1', 9506, 0.5)) { $this->write("链接失败"); } //向服务器发送数据 if (!$client->send($msg)) { $this->write("发送失败"); } //关闭连接 $client->close(); echo '完成'; //注册连接成功回调 // $client->on("connect", function($cli) { // $cli->send("hello world "); // }); //注册数据接收回调 // $client->on("receive", function($cli,$data){ // echo "Received: ".$data." "; // }); //注册连接关闭回调 // $client->on("close", function($cli,$data){ // echo "Received: ".$data." "; // }); }

    访问index方法,来向服务端发送异步任务,这里用send是把需要操作的url发送过去

    以上就是简单的swoole异步

    日常拖更中....

  • 相关阅读:
    CentOS7 安装Docker 18.09.5
    CentOS7 安装Jenkins 2.164.2
    Python3从零开始爬取今日头条的新闻【一、开发环境搭建】
    Win10 安装Oracle11g2、配置PL/SQL Developer11环境
    IDEA 使用Mybatis效率飞起来的必备工具:MybatisCodeHelperPro 最新破解版,亲测可用!
    Navicat Premium 12 (64位)实现连接Oracle 11 (64位)
    VMware14 安装CentOS7 实现宿主机ping通虚拟机、虚拟机ping通宿主机、虚拟机能上网且能ping通百度
    Java中util.Date通过mybatis向数据库中datetime的操作!
    Java中try-catch-finally语句中return的执行顺序总结
    java中this用法总结
  • 原文地址:https://www.cnblogs.com/emmmmmm/p/10167678.html
Copyright © 2011-2022 走看看