PHP开启异步多线程执行脚本

Posted hjcan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP开启异步多线程执行脚本相关的知识,希望对你有一定的参考价值。

场景要求

客户端调用服务器a.php接口,需要执行一个长达5s-20s不等的耗资源操作,但是客户端响应请求时间为5秒(微信公众账号服务器请求响应超时时间),5s以上无回复即断开连接。

解决设想

客户端调用a.php之后,a.php执行异步多线程操作调用b.php,a.php调用成功后即刻反馈给客户端回执,b.php自动执行耗资源操作。

PHP没有真正实现多线程操作的方法。所以需要通过其它手段来进行模拟多线程。

方案一

利用CURL非阻塞调用b.php,实现过程可以参考http://blog.csdn.net/linvo/article/details/5956629
但是有一个问题,就是a.php会继续等待b.php的响应。
于是临时想了一个解决方案:
在此处代码中,将$curlopt_timeout改为1
  1. /**  
  2.      * 单个CURL调用超时限制   
  3.      */    
  4.     public $curlopt_timeout = 1;    
  5.     private $param = array();    
但是这样做就违背了curl本身的逻辑限制。
 

方案二

利用socket在a.php中加入以下代码
  1. $fp = fsockopen("test.com", 80, $errno, $errstr, 30);  
  2. if (!$fp){  
  3.     echo ‘error fsockopen‘;  
  4. }  
  5. else{  
  6.     stream_set_blocking($fp,0);  
  7.     $http = "GET /test/b.php HTTP/1.1 ";      
  8.     $http .= "Host: test.com ";      
  9.     $http .= "Connection: Close ";  
  10.     fwrite($fp,$http);  
  11.     fclose($fp);  
  12. }  
即可实现a.php调用b.php无阻塞。
代码中stream_set_blocking函数用来设定socket链接为无阻塞方式(默认为阻塞)。
 
在使用方案二以后,遇到了一个问题,即客户端短时间内多次调用a.php,出现部分请求 没有执行b.php 的情况。
解决方法:在nginx的nginx.conf文件中,查看worker_processes为1,判断服务端响应请求的线程启动限制太大,得知服务器本身配置为双核CPU,判断2-4线程比较合适,于是修改worker_processes为4.问题得到解决!
 
 

以上是关于PHP开启异步多线程执行脚本的主要内容,如果未能解决你的问题,请参考以下文章

通俗易懂的php多线程解决方案

php 异步执行脚本

总结异步编程的六种方式

PHP开启多线程扩展

PHP异步执行后台的脚本命令

springboot 多线程执行