PHP并行编程探索之二(curl_multi函数组)

      使用pcntl扩展实现的多进程终究只能运行在命令行模式,而我们接触的基本上都处在http请求模式下,那就真没有解决办法了么,有人说用curl,自身请求自身,好我们用curl看一下是不是有用:

       为方便访问和调试,我使用的是CI框架,直接在控制器里操作。

1. 使用curl

(1) 首先我们添加一个耗时计算函数

function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }

(2) 然后直接使用Welcome.php 下的Welcome 控制器

class Welcome extends CI_Controller 
{

	public function index()
    { 
        $url = 'http://web.iyy.com/welcome/task?task_id=';
        $start=microtime_float();	
        $len = 2;
        for($i=0;$i<$len; $i++){
            $this->curl($url.$i);
        }       
        $end=microtime_float();
        echo "\n",$end-$start;
    }
    
    public function curl($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
    
    public function task()
    {
        $task_id = $_REQUEST['task_id'];
        if($task_id == 0){
            sleep(2);  //模拟任务执行时间 2s
            echo '2222'."\n";
        }else{
            sleep(3); //模拟任务执行时间 3s
            echo '3333'."\n";
        }
    }
}

这个例子里,我们做了一个循环请求curl,然后使用参数控制请求的任务,使用sleep模拟任务耗时,最终执行结果如下:

PHP并行编程探索之二(curl_multi函数组)_第1张图片

根据运行结果,我们看到,curl并没有给我们什么实质性的改变,仍然花费了5s多完成。


2. 使用curl_multi函数组

(1)  引入curl_multi封装类

class MultiCurl
{
    /*@var array $config*/
    private $config = array();
    /*@var string $baseUrl*/
    private $baseUrl = '';
    /**
     * @todo: 设置基础路径
     */
    public function setBaseUrl($url = '')
    {
        $this->baseUrl = $url;
        return $this;
    }
    /**
     * @todo: 设置配置参数
     */
    public function setConfig($config = array())
    {
        $baseUrl = $this->baseUrl ? $this->baseUrl : '';
        foreach($config as $val){
            $this->config[] = array(
                'url' => $baseUrl . $val['url']
            );
        }
        return $this;
    }
    /**
     * @todo: 获取查询结果
     */
    public function getRes()
    {
        //2.加入子curl 
        $ch_arr= array();
        $mh = curl_multi_init();
        foreach($this->config as $k=>$val){
        	$ch_arr[$k] = curl_init();
        	curl_setopt($ch_arr[$k], CURLOPT_URL, $val['url']);
        	if(isset($ch_arr[$k]['configs'])){
        		foreach($ch_arr[$k]['configs'] as $kconfig => $config){
        		    curl_setopt($ch_arr[$k], $kconfig, $config);	
        		}
        	}
            curl_setopt($ch_arr[$k], CURLOPT_HEADER, 0);
        	curl_multi_add_handle($mh,$ch_arr[$k]);
        }
        //3.执行curl
        $active = null;
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) == -1) {
                usleep(100);
            }
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
        //4.关闭子curl
        foreach($ch_arr as $val){
            curl_multi_remove_handle($mh, $val);
        }
        //5.关闭父curl
        curl_multi_close($mh);
        //6.获取执行结果
        foreach($ch_arr as $val){
        	$response[] = curl_multi_getcontent($val);
        }
        return $response;
    }
}


(2) 更改welcome控制器

class Welcome extends CI_Controller 
{

	public function index()
    {
        $start=microtime_float();
        $multicurl = new MultiCurl();
        $baseurl = 'http://web.iyy.com';
        $curl_configs = array(
            array('url'=> '/welcome/task?task_id=0'),
            array('url'=> '/welcome/task?task_id=1')
        );
        $res = $multicurl->setBaseUrl($baseurl)->setConfig($curl_configs)->getRes();
        $end=microtime_float();
        echo "\n",$end-$start;
    }
    
    public function task()
    {
        $task_id = $_REQUEST['task_id'];
        if($task_id == 0){
            sleep(2);  //模拟任务执行时间 2s
            echo '2222'."\n";
        }else{
            sleep(3); //模拟任务执行时间 3s
            echo '3333'."\n";
        }
    }
}

这里我们使用了curl_multi函数组,同样的使用curl请求,我们看返回的结果:

PHP并行编程探索之二(curl_multi函数组)_第2张图片

看来两个任务都执行完了,但是基本上,只耗费了最长任务需要的时间,并不是两个任务的总时间,符合我们并行编程的需求,但是话又说回来了,如果我们

并发量很大的前提下,每个请求同时发起两个或者更多的请求,那负载就又上来了,速度是提上来了,访问极限量却变小了,所以这个方案,只能适合访问数不多,但是要考虑访问效率的网站











你可能感兴趣的:(PHP,并行)