3、多进程

PHP是单进程执行的,在处理高并发时主要依赖于Web服务器或PHP-FPM的多进程管理以及进程的复用,但在PHP实现多进程尤其是后台PHP-CLI模式下处理大量数据或运行后台Deamon守护进程时,多进程的优势自然是最好的。
PHP的多线程也曾被人提及,但进程内多线程资源共享和分配问题难以解决,PHP有一个多线程过的扩展pthreads,它要求PHP环境必须是线程安全的。
多进程简单来说就是多个进程同时执行多个任务,可以将耗时但又必须执行的查询分成多个子进程进行操作。

  1. PHP多进程不支持PHP-FPMCGI模式,只能通过PHP-CLI模式。
  2. PHP多进程适用于定时任务执行,互斥且耗时的任务。

开发使用PHP多进程的场景也就是使用PHP-FPM,PHP-FPM作为PHP的多进程管理器,当使用Nginx作为WebServer时,来自客户端的请求会根据Nginx的路由配置,将以PHP为后缀的文件转发给PHP-FPM。当多个用户同时请求API时,PHP-FPM会开启多个PHP的处理进程进行处理。
检查原生PHP是否支持多进程扩展,可以通过查看是否安装了pcntl:

  1. php -m | grep pcntl

多进程的优势

PHP相比C、C++、Java少了多线程,PHP中只有多进程的方案,所以PHP中的全局变量和对象不是共享的,数据结构也不能跨进程操作,另外Socket文件描述符也不能共享…
多线程看似比多进程强大的多,多线程的缺陷也同样明显:

  1. 数据同步时,要么牺牲性能到处加锁,要么使用地狱难度的无锁并发编程。
  2. 当程序逻辑复杂后,锁会越来越难以控制。一旦死锁,程序基本上就完了。
  3. 某个线程挂掉后所有的线程都会退出

相比较多线程,多进程拥有的优势是:

  1. 配合进程间通信,基本可以实现任意数据共享。
  2. 多进程不需要锁
  3. 多进程可以共享内存的数据结构实现一些多线程的功能

对于并发服务器核心是IO,并非大规模密集运算,高并发的服务器单机能维持10W连接,每秒可以处理3~5W笔消息收发。
普通的Web应用都是IO密集型的程序,瓶颈在MySQL上,所以体现不出PHP的性能优势。但在密集计算方面比C/C++、Java等静态编译语言相差几十倍甚至上百倍。
例如:使用Swoole多进程方式同时访问Web地址,multi.php:

  1. <?php
  2. echo "process begin: ".date("Y-m-d H:i:s").PHP_EOL;
  3. //初始化地址数组
  4. $urls = [
  5. "http://www.baidu.com",
  6. "http://www.360.com",
  7. "http://www.qq.com",
  8. "http://www.sina.com"
  9. ];
  10. //初始化数组用于回收线程管道内容
  11. $workers = [];
  12. //按照任务分配线程
  13. for($i=0; $i<count($urls); $i++){
  14. $url = $urls[$i];
  15. //创建进程
  16. $process = new swoole_process(function(swoole_process $worker) use($url){
  17. //模拟执行耗时任务
  18. file_get_contents($url);
  19. //sleep(1);//模拟耗时1秒
  20. echo $url.PHP_EOL;
  21. }, true);
  22. //开启进程
  23. $pid = $process->start();
  24. $workers[$pid] = $process;
  25. }
  26. //打印管道内容
  27. foreach($workers as $worker){
  28. echo "pid : ".$worker->read();
  29. }
  30. echo "process end: ".date("Y-m-d H:i:s").PHP_EOL;

运行代码:

  1. php multi.php

得到输出:

  1. process begin: 2020-05-12 16:19:48
  2. pid : http://www.baidu.com
  3. pid : http://www.360.com
  4. pid : http://www.qq.com
  5. pid : http://www.sina.com
  6. process end: 2020-05-12 16:19:49