PHP异步执行长时间任务

长时间执行的任务不适合放在PHP中执行应当放在任务调度系统或消息系统中由后台程序去执行,但是有时候还是需要在PHP中执行下长时间的任务 ,并且客户端不需要返回值。实现的思路大体如下:首先客户端发起一个不需要等待返回的请求,服务器端则需要忽略请求中断和执行时间,以免中途退出。

当有请求到达时,服务器端执行任务,在这里会产生一个文件。服务器端文件:

<?php 
//ob_start();
//header('Content-Type:text/html;charset=utf-8');
//header('Connection:close');
//flush();

ignore_user_abort(true);//忽略客户端连接中断
set_time_limit(0);//忽略页面执行超时
//Todo:do something here
sleep(10);
fopen(dirname( __FILE__ ).'\\'.time(),  "w");
&#91;/php&#93;

1.使用<a href="http://php.net/manual/en/function.fsockopen.php">fsockopen</a>来请求服务端执行任务,该方法需要自己拼凑header,包括参数等


<?php 
function triggerRequest($url, $post_data = array(), $cookie = array()){         
    $method = "GET";  //可以通过POST或者GET传递一些参数给要触发的脚本         
    $url_array = parse_url($url); //获取URL信息,以便平凑HTTP HEADER         
    $port = isset($url_array&#91;'port'&#93;)? $url_array&#91;'port'&#93; : 80;         
    $fp = fsockopen($url_array&#91;'host'&#93;, $port, $errno, $errstr, 30);         
    if (!$fp){                 
        return FALSE;         
    }         
    $getPath = $url_array&#91;'path'&#93; ."?". $url_array&#91;'query'&#93;;         
    if(!empty($post_data)){                 
        $method = "POST";         
    }         
    $header = $method . " " . $getPath;         
    $header .= " HTTP/1.1\r\n";         
    $header .= "Host: ". $url_array&#91;'host'&#93; . "\r\n "; //HTTP 1.1 Host域不能省略               
    $header .= "Connection:Close\r\n\r\n";         
    if(!empty($cookie)){                 
        $_cookie = strval(NULL);                 
        foreach($cookie as $k =--> $v){
            $_cookie .= $k."=".$v."; ";
        }
        $cookie_str =  "Cookie: " . base64_encode($_cookie) ." \r\n";//传递Cookie
        $header .= $cookie_str;
    }
    if(!empty($post_data)){
            $_post = strval(NULL);
            foreach($post_data as $k => $v){
                    $_post .= $k."=".$v."&";
            }
            $post_str  = "Content-Type: application/x-www-form-urlencoded\r\n";//POST数据
            $post_str .= "Content-Length: ". strlen($_post) ." \r\n";//POST数据的长度
            $post_str .= $_post."\r\n\r\n "; //传递POST数据
            $header .= $post_str;
    }
    fwrite($fp, $header);
    fclose($fp);
    return true;
}
$url='http://127.0.0.1/learn/asyn/server.php';
triggerRequest($url);

2.使用curl来发起请求,可以方便的设置传递参数,cookie等,比fsockopen简洁许多,需要安装php_curl扩展

<?php
 $ch = curl_init();
 $data = array('param' => '1');
 curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1/learn/asyn/server.php');
 curl_setopt($ch, CURLOPT_POST, 1);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
 curl_setopt($ch, CURLOPT_TIMEOUT, 1);//1秒后立即执行
 curl_exec($ch);
 curl_close($ch);

也可以采用popen,ajax发起请求,详见参考链接。
参考链接
fsockopen函数用法
使用fscok实现异步调用PHP
PHP实现异步调用方法研究
说说php的异步请求
php curl常用的5个例子