php实现异步调用无阻塞
之前web端的数据统计用的是嵌入一个img标签,src指向脚本文件/index.php?name=xingdong,这种方法倒是挺快,不过需要的是页面加载,现在是在给客户端写接口,就不太合适.于是找了下解决办法
1.popen() (转)
resource popen ( string command, string mode );
//打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。
所以可以通过调用它,但忽略它的输出。
pclose(popen("/home/xinchen/backend.php &", 'r'));
这个方法避免了第一个方法的缺点,并且也很快。但是问题是,这种方法不能通过HTTP协议请求另外的一个WebService,只能执行本地的脚本文件。并且只能单向打开,无法穿大量参数给被调用脚本。
并且如果,访问量很高的时候,会产生大量的进程。如果使用到了外部资源,还要自己考虑竞争。
2.curl
这个方法,设置CUROPT_TIMEOUT为1(最小为1,郁闷)。也就是说,客户端至少必须等待1秒钟
$ch = curl_init();
$curl_opt = array(CURLOPT_URL, 'http://www.example.com/backend.php',CURLOPT_RETURNTRANSFER, 1,CURLOPT_TIMEOUT, 1,);
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);
3.fsockopen和stream_socket_client,可以直接替换
ps:PHP5中可以使用新增的stream_socket_client()函数直接替换掉fsocketopen()
在使用之前出现了很多问题,我的服务器配置比较低,nginx配置中worker_processes为1,出现了请求后没有异步处理,改成2解决
执行一个时间比较长的异步请求后,不能全部执行,查看php-fpm日志发现
WARNING: [pool www] child 19307, script '/work/www/live/manage/index.php' (request: "GET /index.php") execution timed out (130.098597 sec), terminating
修改php-fpm.ini中的request_terminate_timeout=0解决(不知道还有什么别的坑没有),默认是120
我尝试着用了swoole扩展解决异步,暂时没发现问题,但是要是用swoole的话,所有的服务器都得装,太麻烦了,先这样,如果再出现问题,在用swoole扩展试下
无数据传输
<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp){
echo 'error fsockopen';
}else{
//stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
$http = "GET /index.php HTTP/1.1\r\n";
$http .= "Host:www.example.com\r\n";
$http .= "Connection: Close\r\n\r\n";
fwrite($fp,$http);
//while (!feof($fp)) {
// echo fgets($fp, 128);
// }
//usleep(1000);//如果异步调用不成功,可以加上这句话
fclose($fp);
}
?>
get数据
<?php
$param = array(
'name' => 'xingdong'
);
$url = $url.'?'.http_build_query($param);
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp){
echo 'error fsockopen';
}else{
//stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
$http = "GET ${url} HTTP/1.1\r\n";
$http .= "Host:www.example.com\r\n";
$http .= "Connection: Close\r\n\r\n";
//fputs($fp,$http);
fwrite($fp,$http);
fclose($fp);
}
?>
post数据
<?php
$param = array(
'name' => 'xingdong'
);
$data = http_build_query($param);
$url = '/index.php';
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp){
echo 'error fsockopen';
}else{
//stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
$http = "POST ${url} HTTP/1.1\r\n";
$http .= "Host:www.example.com\r\n";
$http .= "Connection: Close\r\n\r\n";
$http .= "Content-type:application/x-www-form-urlencoded\r\n";
$http .= "Content-length:".strlen($data)."\r\n";
$http .= "Connection:close\r\n\r\n";
$http .= "${data}";
//fputs($fp,$http);
fwrite($fp,$http);
fclose($fp);
}
已有 0 条评论