/**
* @description: 异步执行 (post可行,get需要测试)
* @param url url 脚本地址 www.xxx.com/text.php?var1=data1
* @param timeout int 连接url地址时的超时时间
* @param method string 请求方法 默认get
* @param data array 请求参数数组 默认 []
* @param cookie_array array cookie数组 默认[]
* @return:
*/
function async_exe($url,$timeout = 1,$method = 'get',$data = array(),$cookie_array = null)
{
ignore_user_abort(true); // 忽略客户端断开
set_time_limit(0); // 设置执行不超时
$cookie = '';
foreach ($cookie_array as $k=>$v) {
$cookie .= urlencode($k) .'='. urlencode($v) .'; ';
}
$urlinfo = parse_url($url);
$urlinfo['port'] = $urlinfo['port'] == 0 ? 80 : $urlinfo['port'];
$query = !empty($data)? http_build_query($data) : '';
//拼接请求头
$crlf = "\r\n";
$head_method = $method == 'post' ? 'POST ' : 'GET ';
$out = $head_method.$urlinfo['path'].' HTTP/1.1'.$crlf;
$out .= 'Host: '.$urlinfo['host'].$crlf;
if (!empty($cookie)) $out .= 'Cookie: '.substr($cookie, 0, -2).$crlf;
if ($method == 'post' && !empty($data)) {
$out .= 'Content-length: '.strlen($query).$crlf;
$out .= 'Content-type: application/x-www-form-urlencoded'.$crlf;
$out .= 'Connection: close'.$crlf.$crlf;
$out .= $query.$crlf.$crlf;
} else {
$out .= 'Connection: close'.$crlf.$crlf;
}
$errno = 0;
$errstr = '';
$fp = fsockopen($urlinfo['host'], $urlinfo['port'], $errno, $errstr, $timeout);
stream_set_blocking($fp,true);
stream_set_timeout($fp,1);
fputs($fp, $out);
// while (!feof($fp)) { //可以查看返回信息(变成同步了),测试
// echo fgets($fp,128);
// }
//fwrite之后马上执行fclose,nginx会直接返回499,原因:客户端主动断开请求连接时,NGINX 不会将该请求代理给上游服务,设置休眠20毫秒可以避免这种情况
usleep(20000);
fclose($fp);
}
/**
* @description: 异步执行
* @param url url 脚本地址 http://xxx.xxx.xxx?var1=data1
* @param method string 请求方法
* @param params array 请求参数数组
* @param cookie_array array cookie数组
* @return:
*/
function async_exe1($url,$method = 'get',$params = array(),$cookie_array = array())
{
$ch = curl_init();
$curl_opt = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1, //获取的信息以文件流的形式返回,而不是直接输出。
CURLOPT_TIMEOUT => 1, //允许 cURL 函数执行的最长秒数
);
if ($method == 'post') {
$curl_opt[CURLOPT_POST] = true;
$curl_opt[CURLOPT_POSTFIELDS] = http_build_query($params);
}
if (!empty($cookie_array)) {
$cookie = '';
foreach ($cookie_array as $k=>$v) {
$cookie .= urlencode($k) .'='. urlencode($v) .'; ';
}
$curl_opt[CURLOPT_COOKIE] = $cookie;
}
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);
}
/**
* @description: 异步执行 只能执行本地的脚本文件。并且只能单向打开,无法传大量参数给被调用脚本。并且如果,访问量很高的时候,会产生大量的进程。
* @param path string 脚本地址 /home/xinchen/backend.php
* @return:
*/
function async_exe2($path)
{
pclose(popen("php $path &", 'r'));
}
// 只有在FastCGI模式下存在,将echo的值返回给用户后,在此函数下面的代码将会继续执行,但是会关闭链接,
// 在fastcgi_finish_request()之后,脚本仍然会占用一个FPM进程。
// 只要会话处于活动状态,它们就会被锁定。这意味着后续的请求将被阻塞,直到会话关闭,应该尽快调用session_write_close()(甚至在fastcgi_finish_request()之前),以允许后续请求和良好的用户体验
// 只要一个锁处于活动状态(例如群锁或数据库锁),后续的请求就可能被锁住。
// windows上没有FPM,所以没有这个函数;linux上有
echo '返回值';
fastcgi_finish_request();