加入收藏 | 设为首页 | 会员中心 | 我要投稿 草根网_马鞍山站长网 (https://www.0555zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

PHP异步非阻塞的实现方法

发布时间:2022-10-18 12:41:00 所属栏目:教程 来源:
导读:  前言

  由于PHP本身是一种单进程的语言,每次请求在apache都是一个进程,在Nginx和fastCGI里面每个请求时一个单独的worker线程,而且在各个服务器里面的请求都是阻塞的,所以有些大批量的复杂逻辑或文本处
  前言
 
  由于PHP本身是一种单进程的语言,每次请求在apache都是一个进程,在Nginx和fastCGI里面每个请求时一个单独的worker线程,而且在各个服务器里面的请求都是阻塞的,所以有些大批量的复杂逻辑或文本处理会导致请求响应时间很长,这里我们就要考虑让PHP实现异步非阻塞的做法,已达到减少响应时间的目的。
 
  一、各种实现方法
 
  1、FastCGI的非阻塞方法:fastcgi_finish_request()
 
  在PHP5.3.3版本之后,不管是Nginx还是Apache服务器,只要运行在FastCGI模式下,均可使用该方法,官方解释的作用是冲刷(flush)所有响应的数据给客户端。
 
  boolean fastcgi_finish_request ( void )
 
  此函数冲刷(flush)所有响应的数据给客户端并结束请求。 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行。
 
  用法:可以在读写大文件、循环更新数据库等不影响结果的操作之前,执行该函数,把结果返回给客户端,php会继续执行下面的逻辑而不影响客户端的响应时间。
 
  2、fsockopen()+stream_set_blocking()方法:
 
  fsockopen()方法可以打开一个网络连接或Unxi套接字连接,stream_set_blocking()方法可以为资源流设置非阻塞或者阻塞模式,
 
  使用fsockopen()打开一个网络连接或者一个Unix套接字连接,再用stream_set_blocking()设置资源成非阻塞模式请求php单线程,则该资源请求会是非阻塞的:
 
  bool stream_set_blocking ( resource $stream , int $mode )
 
  注:$mode=0则是非阻塞的,1则是阻塞的模式。
 
  用法:
 
  php单线程_多线程调用单例类中的方法会不会造成线程安全问题?_php进程和线程
 
  3、使用cURL执行异步请求:
 
  cURL除了我们通常使用的curl_init来初始化和发送post和get请求之外,还可以使用curl_multi_init()方法来实现异步请求,其原理是使用系统的select这个多路I/O复用机制来异步发送请求。
 
  通常的用法:
 
  php进程和线程_多线程调用单例类中的方法会不会造成线程安全问题?_php单线程
 
  异步用法:
 
  php单线程_多线程调用单例类中的方法会不会造成线程安全问题?_php进程和线程
 
  4、使用Gearman/Swoole等PHP异步扩展或框架
 
  5、使用缓存和队列
 
  通常复杂的处理逻辑,我们可以将参数推入队列,如redis或kafka的队列服务,开启一个消费进程去处理队列事务。
 
  如redis服务的list结构,在之前篇章有过说明。
 
  6、使用pcntl_fork()
 
  在PHP4.1.0版本之后都支持了该函数,使用前需要安装支持pcntl扩展并添加支持。
 
  官方文档:在当前进程当前位置产生分支(子进程),这个子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同
 
  说明:int pcntl_fork ( void )
 
  成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0;
 
  失败时,在父进程上下文返回-1,不会创建子进程,并且会引发一个PHP错误。
 
  用法:
 
  php单线程_多线程调用单例类中的方法会不会造成线程安全问题?_php进程和线程
 
  二、优劣对比
 
  并发IO问题一直是服务器端编程中的技术难题,从最早的同步阻塞直接Fork进程,到Worker进程池/线程池,到现在的异步IO、协程。阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。现在网络的日益发展,对响应时间和处理并发的要求越来越高,所以异步非阻塞的需求也越来越多,优点也显而易见:
 
  1、非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程,能及时返回响应,减少响应时间;
 
  2、高并发,同步阻塞IO模型的并发能力依赖于进程/线程数量,响应时间的下降可以带来更多的并发能力。
 
  当然,异步非阻塞又存在缺点:
 
  1、启动大量进程会带来额外的进程调度消耗。非阻塞模式下,如果大量线程已经返回响应而仍然在执行计算操作,会使CPU利用率不可控的增高;
 
  2、这种模型严重依赖进程的数量解决并发问题,一个客户端连接就需要占用一个进程,工作进程的数量有多少,并发处理能力就有多少。操作系统可以创建的进程数量是有限的;
 
  3、过多的异步和多线程模型会造成编码困难或线程混乱,如出现大量僵尸进程等。
 
  三、总结
 
  1、一般情况下,我们不赞成用异步回调的方式去做功能开发,传统的PHP同步方式实现功能和逻辑是最简单的,也是最佳的方案。像node.js这样到处callback,只是牺牲可维护性和开发效率;
 
  2、有些时候很适合用异步,比如FTP、聊天服务器,smtp,代理服务器等等此类以通信和读写磁盘为主,功能和业务逻辑其次的服务器程序;
 
  3、异步非阻塞和多线程模型推荐:
 
  (1)swoole框架:fpm里,通过swoole_client把url发送到swoole的server,swoole_server天然支持并行请求,把汇总的结果返回到fpm;
 

(编辑:草根网_马鞍山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!