当客户端访问服务端一个api接口,而服务端有时执行一些耗费时间的任务(结果不需要返回客户),由于PHP本身的特性(单线程,同步进行),要等服务端完成任务了才返回结果给客户端。可以先将结果返回给客户端,同时服务端异步执行耗时的任务。
以下有几段代码可以实现异步操作:
function _curl($url,$params) {
$ch = curl_init();
$headers = array("Content-type: application/json;charset='utf-8'",
"Accept: application/json",
"Cache-Control: no-cache","Pragma: no-cache");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);//设置提交的字符串
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //设置头信息
curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1 ); //获取的信息以文件流的形式返回
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不进行ssl验证
curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
//设置超时时间为1秒,超过1秒则关闭连接
// curl_setopt($ch,CURLOPT_TIMEOUT,1); // 超时秒
curl_setopt($ch, CURLOPT_NOSIGNAL, 1); //注意,毫秒超时一定要设置这个
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); //超时毫秒,cURL 7.16.2中被加入。从PHP 5.2.3起可使用
curl_setopt($ch, CURLOPT_HEADER, 0); // 设置是否显示返回头信息 1返回 0不返回
curl_setopt($ch, CURLOPT_NOBODY, 0); //不想在输出中包含body部分,设置这个选项为一个非零值
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result);
}
function syncRequest($url, $param=array(),$postData="",$timeout =10)
{
$urlParmas = parse_url($url);
$host = $urlParmas['host'];
$path = $urlParmas['path'];
$scheme = $urlParmas['scheme'];
$port = isset($urlParmas['port'])? $urlParmas['port'] :80;
$errno = 0;
$errstr = '';
if($scheme == 'https') {
$host = 'ssl://'.$host;
}
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
stream_set_blocking($fp,true);//开启了手册上说的非阻塞模式
$query = isset($param)? http_build_query($param) : '';
//如果传递参数在body中,则使用
if(!empty($postData)) $query = $postData;
$out = "PUT ".$path." HTTP/1.1\r\n";
$out .= "host:".$host."\r\n";
$out .= "content-length:".strlen($query)."\r\n";
//传递参数为url=?p1=1&p2=2的方式,使用application/x-www-form-urlencoded方式
//$out .= "content-type:application/x-www-form-urlencoded\r\n";
//传递参数为json字符串的方式,并且在请求体的body中,使用application/json
$out .= "content-type:application/json\r\n";
$out .= "connection:close\r\n\r\n";
$out .= $query;
fputs($fp, $out);
$result = "";
fclose($fp);
}
function doRequest($url, $param=array()){
$urlinfo = parse_url($url);
var_dump($urlinfo);
$host = $urlinfo['host'];
$path = $urlinfo['path'];
$query = isset($param)? http_build_query($param) : '';
$port = 80;
$errno = 0;
$errstr = '';
$timeout = 10;
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
$out = "POST ".$path." HTTP/1.1\r\n";
$out .= "host:".$host."\r\n";
$out .= "content-length:".strlen($query)."\r\n";
$out .= "content-type:application/x-www-form-urlencoded\r\n";
$out .= "connection:close\r\n\r\n";
$out .= $query;
fputs($fp, $out);
fclose($fp);
}
以上代码经过测试都可以用,注意在_curl()方法中,如果设置毫秒超时,CURLOPT_TIMEOUT_MS 设置太小的话,异步执行操作可能失败(不执行),在测试中设置为150ms,没有问题,但是设置为100ms,异步执行操作失败,但不影响返回结果给客户端
感谢博主,喝杯咖啡~
还没有人发表评论