当前位置:首页 > PHP教程 > php高级应用 > 列表

php中使用fsockopen实现异步请求(代码示例)

发布:smiling 来源: PHP粉丝网  添加日期:2022-05-26 10:41:55 浏览: 评论:0 

php执行一段程序,有可能几毫秒就执行完毕,也有可能耗时较长。

例如,用户下单这个事件,如果调用了些第三方服务进行发邮件、短信、推送等通知,可能导致前端一直在等待。

而有的时候,我们并不关心这些耗时脚本的返回结果,只要执行就行了,这时候就需要采用异步的方式执行。

众所周知,PHP没有直接支持多线程这种东西,我们可以采用折衷的方式实现,这里主要说的就是fsockopen。

通过fsockopen发送请求并忽略返回结果,程序可以马上返回。

示例代码:

  1. $fp = fsockopen("www.example.com", 80, $errno$errstr, 30); 
  2.  
  3. if (!$fp) { 
  4.  
  5.     echo "$errstr ($errno)<br />\n"
  6.  
  7. else { 
  8.  
  9.     $out = "GET /backend.php   HTTP/1.1\r\n"
  10.  
  11.     $out .= "Host: www.example.com\r\n"
  12.  
  13.     $out .= "Connection: Close\r\n\r\n"
  14.  
  15.    
  16.  
  17.     fwrite($fp$out); 
  18.  
  19.     /*忽略执行结果 
  20.  
  21.     while (!feof($fp)) { 
  22.  
  23.         echo fgets($fp, 128); 
  24.  
  25.     }*/ 
  26.  
  27.     fclose($fp); 
  28.  

需要注意的是我们需要手动拼出header头信息,通过打开注释部分,可以查看请求返回结果,但这时候又变成同步的了,因为程序会等待返回结果才结束。

实际测试的时候发现,不忽略执行结果,调试的时候每次都会成功发送sock请求;但忽略执行结果,经常看到没有成功发送sock请求。查看nginx日志,发现很多状态码为499的请求。

后来找到了原因:

fwrite之后马上执行fclose,nginx会直接返回499,不会把请求转发给php处理。

客户端主动端口请求连接时,NGINX 不会将该请求代理给上游服务(FastCGI PHP 进程),这个时候 access log 中会以 499 记录这个请求。

解决方案:

1)nginx.conf增加配置

# 忽略客户端中断

fastcgi_ignore_client_abort on;

2)fwrite之后使用usleep函数休眠20毫秒:

usleep(20000);

后来测试就没有发现失败的情况了。

附上完整代码:

  1. <?php 
  2.  
  3. /** 
  4.  
  5.  * 工具类 
  6.  
  7.  * */ 
  8.  
  9. class FsockService { 
  10.  
  11.       
  12.  
  13.     public static function post($url$param){ 
  14.  
  15.         $host = parse_url($url, PHP_URL_HOST); 
  16.  
  17.         $port = 80; 
  18.  
  19.         $errno = ''
  20.  
  21.         $errstr = ''
  22.  
  23.         $timeout = 30; 
  24.  
  25.         $data = http_build_query($param); 
  26.  
  27.         // create connect 
  28.  
  29.         $fp = fsockopen($host$port$errno$errstr$timeout); 
  30.  
  31.         if(!$fp){ 
  32.  
  33.             return false; 
  34.  
  35.         } 
  36.  
  37.         // send request 
  38.  
  39.         $out = "POST ${url} HTTP/1.1\r\n"
  40.  
  41.         $out .= "Host:${host}\r\n"
  42.  
  43.         $out .= "Content-type:application/x-www-form-urlencoded\r\n"
  44.  
  45.         $out .= "Content-length:".strlen($data)."\r\n"
  46.  
  47.         $out .= "Connection:close\r\n\r\n"
  48.  
  49.         $out .= "${data}"
  50.  
  51.         fwrite($fp$out); 
  52.  
  53.         //忽略执行结果;否则等待返回结果 
  54.  
  55. //        if(APP_DEBUG === true){ 
  56.  
  57.         if(false){ 
  58.  
  59.             $ret = ''
  60.  
  61.             while (!feof($fp)) { 
  62.  
  63.                 $ret .= fgets($fp, 128); 
  64.  
  65.             } 
  66.  
  67.         } 
  68.  
  69.         usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499 
  70.  
  71.         fclose($fp); 
  72.  
  73.     } 
  74.  
  75.     public static function get($url$param){ 
  76.  
  77.         $host = parse_url($url, PHP_URL_HOST); 
  78.  
  79.         $port = 80; 
  80.  
  81.         $errno = ''
  82.  
  83.         $errstr = ''
  84.  
  85.         $timeout = 30; 
  86.  
  87.         $url = $url.'?'.http_build_query($param); 
  88.  
  89.         // create connect 
  90.  
  91.         $fp = fsockopen($host$port$errno$errstr$timeout); 
  92.  
  93.         if(!$fp){ 
  94.  
  95.             return false; 
  96.  
  97.         } 
  98.  
  99.         // send request 
  100.  
  101.         $out = "GET ${url} HTTP/1.1\r\n"
  102.  
  103.         $out .= "Host:${host}\r\n"
  104.  
  105.         $out .= "Connection:close\r\n\r\n"
  106.  
  107.         fwrite($fp$out); 
  108.  
  109.         //忽略执行结果;否则等待返回结果 
  110.  
  111. //        if(APP_DEBUG === true){ 
  112.  
  113.         if(false){ 
  114.  
  115.             $ret = ''
  116.  
  117.             while (!feof($fp)) { 
  118.  
  119.                 $ret .= fgets($fp, 128); 
  120.  
  121.             } 
  122.  
  123.         } 
  124.  
  125.         usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499 
  126.  
  127.         fclose($fp); 
  128.  
  129.     } 
  130.  
  131.      
  132.  
  133.  
  134. ?>

Tags: fsockopen php异步请求

分享到: