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);

  }