php从代码级别的执行上是单线程的, 但是由php-fpm进程管理机制是多进程单线程的, 也就是php是多进程执行的. 有效提高并发的响应效率。了解关于cgi、fastCGI、php-cgi、php-fpm的概念更能加深理解。

下面是我查阅大量资料后整理的关系图供大家参考,也欢迎留言一起讨论。

1. CGI

CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上(在fastcig未使用前是运行在网络服务器上的,具体请看下文)。

CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,tcl等。cgi是一个web server与cgi程序(这里可以理解为是php解释器)之间进行数据传输的协议,保证了传递的是标准数据。

2. FastCGI

FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算,即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等

2.1 FastCGI特点

FastCGI具有语言无关性。

FastCGI在进程中的应用程序,独立于核心web服务器运行,提供了一个比API更安全的环境。APIs把应用程序的代码与核心的web服务器链接在一起,这意味着在一个错误的API的应用程序可能会损坏其他应用程序或核心服务器。恶意的API的应用程序代码甚至可以窃取另一个应用程序或核心服务器的密钥。

FastCGI技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby等。相关模块在Apache, ISS, Lighttpd等流行的服务器上也是可用的。

FastCGI的不依赖于任何Web服务器的内部架构,因此即使服务器技术的变化, FastCGI依然稳定不变。

2.2 FastCGI的工作原理

Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)

FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。

当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。

FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。在CGI模式中,php-cgi在此便退出了。

在上述情况中,你可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。

2.3 FastCGI的不足

因为是多进程,所以比CGI多线程消耗更多的服务器内存,PHP-CGI解释器每进程消耗7至25兆内存,将这个数字乘以50或100就是很大的内存数。

Nginx 0.8.46+PHP 5.2.14(FastCGI)服务器在3万并发连接下,开启的10个Nginx进程消耗150M内存(15M10=150M),开启的64个php-cgi进程消耗1280M内存(20M64=1280M),加上系统自身消耗的内存,总共消耗不到2GB内存。如果服务器内存较小,完全可以只开启25个php-cgi进程,这样php-cgi消耗的总内存数才500M。

上面的数据摘自Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)

3. PHP-CGI

php-cgi 是 php 的解释器,就是上文提到的cgi程序。

关于PHP-CGI是PHP自带的FastCGI管理器的说法。

我是这么理解的:

第一:CGI解释器(php-cgi)保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等,也就是在fast-cgi层面是管理着多个CGI程序(php-cgi)的进程的。

第二:fpm官方的解释是:FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的

(https://www.php.net/manual/zh/install.fpm.php)。

所以我不认同PHP-CGI是PHP自带的FastCGI管理器的说法。

3.1 PHP-CGI 的不足

php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。

直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程。)

4. PHP-FPM(php Fastcgi Process Manager)

PHP-FPM是一个PHP FastCGI管理器,是只用于PHP的,可以在 http://php-fpm.org/download下载得到。

PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。

现在我们可以在最新的PHP 5.3.2的源码树里下载得到直接整合了PHP-FPM的分支,据说下个版本会融合进PHP的主分支去。相对Spawn-FCGI,PHP-FPM在CPU和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用crontab进行监控,而PHP-FPM则没有这种烦恼。

PHP5.3.3已经集成php-fpm了,不再是第三方的包了。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,比spawn-fcgi具有更多有点,所以被PHP官方收录了。在./configure的时候带 –enable-fpm参数即可开启PHP-FPM。

5 PHP对并发访问的处理

5.1 进程和线程

PHP从代码级别来讲不支持多线程操作,不能像Java、C#等语言一样可以编写多线程代码。但多线程和并发没有直接关系,多线程只是代码被运行时在同一时间同时执行多个线程任务,来提高服务器CPU的利用率,提高代码效率。但php是可以多进程执行的,上文所述的FPM进程管理机制就是多进程单线程的,有效提高了并发访问的响应效率。

5.2 简单的web server + php-fpm 模式

当客户端发送一个请求时,web server会通过一个php-fpm进程(这里和下文所说指的fpm进程都是fpm开启的worker进程,关于fpm的工作原理这里不再累述)去执行php代码,php代码的执行是单线程的。

那么,当有多个客户端同时发送请求时(并发),web server会通过php-fpm为每个请求开启一个单独进程去执行php代码。

请求执行过后,空闲的php-fpm进程被销毁,内存得以释放。

但并发的问题在于,在某一时间,客户端请求让php-fpm进程数量达到了最大限制数,这个时候,新来的请求只能等待空闲的php-fpm进程来处理,这就是多进程同步阻塞模式的弊端,当然还有进程过多所带来的内存占用问题。

6.高并发和多线程

“高并发和多线程”总是被一起提起,给人感觉两者好像相等,实则 高并发 ≠ 多线程。多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现。

高并发是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。

如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……而多线程只是其中解决方法之一。实现高并发需要考虑:

1. 系统的架构设计,如何在架构层面减少不必要的处理(网络请求,数据库操作等)

2. 网络拓扑优化减少网络请求时间、如何设计拓扑结构,分布式如何实现?

3. 系统代码级别的代码优化,使用什么设计模式来进行工作?哪些类需要使用单例,哪些需要尽量减少new操作?

4. 提高代码层面的运行效率、如何选取合适的数据结构进行数据存取?如何设计合适的算法?

任务执行方式级别的同异步操作,在哪里使用同步,哪里使用异步?

5. JVM调优,是以server模式还是以clien模式运行,如何设置Heap、Stack、Eden的大小,如何选择GC策略,控制Full GC的频率?

6. 数据库优化减少查询修改时间。数据库的选取?数据库引擎的选取?数据库表结构的设计?数据库索引、触发器等设计?是否使用读写分离?还是需要考虑使用数据仓库?

7. 缓存数据库的使用,如何选择缓存数据库?是Redis还是Memcache? 如何设计缓存机制?

8. 数据通信问题,如何选择通信方式?是使用TCP还是UDP,是使用长连接还是短连接?NIO还是BIO?netty、mina还是原生socket?

9. 操作系统选取,是使用winserver还是Linux?或者Unix?

10 硬件配置?是8G内存还是32G,网卡10G还是1G?

...

以上的这些问题在高并发中都是必须要深入考虑的,就像木桶原理一样,只要其中的某一方面没有考虑到,都会造成系统瓶颈,影响整个系统的运行。而高并发问题不仅仅涉及面之广,同时又要求有足够的深度!!!

而多线程在这里只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。多线程在解决高并发问题中所起到的作用就是使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

参考:

https://www.php.cn/php-weizijiaocheng-377248.html、https://www.cnblogs.com/zuochuang/p/7885941.html、https://www.php.net/manual/zh/install.fpm.php、https://www.cnblogs.com/itxiongwei/p/9072075.html

岁月峥嵘

不忘初心

-PHP开源社区-忌

平庸懒惰

不求上进

php 每天早上八点执行操作_php多进程单线程之phpcgi、phpfpm相关推荐

  1. python启动多个进程_Python程序中的进程操作--—--开启多进程

    Python程序中的进程操作-----开启多进程 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创 ...

  2. 【奇巧淫技】python 助你每天早上八点自动发送天气预报邮件到QQ邮箱

    此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉. 补充 有不少杠精小婊贝留言说本文章没有用,因为天气预报直接打开手机就可以收到了,为何要多此一举发送到邮箱呢!! ...

  3. python向自己qq邮箱发信息_【奇巧淫技】python!每天早上八点自动发送天气预报邮件到QQ邮箱...

    本文为CSDN博主「SunriseCai」的原创文章 补充 有不少读者留言说本文章没有用,因为天气预报直接打开手机就可以收到了,为何要多此一举发送到邮箱呢!!!那我在这里只能说:因为你没用,所以你没用 ...

  4. tensorflow tf.enable_eager_execution()(立即执行操作,不添加到稍后在“ tf.Session”中执行的图)

    @tf_export("enable_eager_execution") def enable_eager_execution(config=None,device_policy= ...

  5. python paramiko并发_使用Python paramiko模块利用多线程实现ssh并发执行操作

    1.paramiko概述 ssh是一个协议,OpenSSH是其中一个开源实现,paramiko是Python的一个库,实现了SSHv2协议(底层使用cryptography). 有了Paramiko以 ...

  6. JDBC连接数据库及其执行操作

    作者:Alvin 功能:数据库连接与实现增删改查 时间:2019年3月4日08点33分 参考文章:https://www.2cto.com/database/201805/743741.html 一. ...

  7. cout输出数组_让程序从1开始一直执行++操作,10秒钟能输出最大的数是多少

    问题描述 如果写一段代码,让程序从 1 开始一直执行 ++ 操作,在规定的 10s 钟内,你能输出的最大数是多少?并将它打印到屏幕上. 乍一看,你会觉得它是一道算法题,再细想:不对!这可能是一道性能题 ...

  8. LeetCode 1625. 执行操作后字典序最小的字符串(BFS)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串 s 以及两个整数 a 和 b .其中,字符串 s 的长度为偶数,且仅由数字 0 到 9 组成. 你可以在 s 上按任意顺序多次执行下面两个 ...

  9. 对广义表L=((a,b),(c,d),(e,f))执行操作tail(tail(L))的结果是 ()

    对广义表L=((a,b),(c,d),(e,f))执行操作tail(tail(L))的结果是 (  ) . A.(e,f) B.((e,f)) C.(f) D.() 本题考查广义表的概念和特征. 广义 ...

最新文章

  1. ADO.NET五大对象详解
  2. C#程序中设置全局代理(Global Proxy)
  3. wxWidgets:wxConfig 和相关类的演示
  4. 原生sql实现restful接口调用
  5. Caffe 增加自定义 Layer 及其 ProtoBuffer 参数
  6. CCF受理“大数据专家委员会”2019年委员与通讯委员申请
  7. 怎么画闭合线_骨骺线闭合怎么长高
  8. 随想录(公司程序员的九层楼)
  9. androidpn的学习研究(四)androidpn-client客户端几个类说明
  10. OSG仿真案例(7)——osg自动驾驶
  11. 6月7日 PowerPoint 版本支持的媒体格式(跨office版本演示需要了解)
  12. 潜利KINGLEE触摸屏维修喷码机显示屏电脑
  13. gif动态图批量加水印方法
  14. word字间距怎么调整成一样的【word教程】
  15. 魔兽世界插件编写-第一个插件-空插件 EmptyAddOns
  16. Java个人职业规划目标改进_java个人职业发展方向规划范文
  17. 机器学习算法:K近邻(k-nearest neighbors)
  18. 获取android应用缓存目录时遇到的问题
  19. Illumina测序原理
  20. 阿里云云开发平台的创建与部署

热门文章

  1. 要成为linux网站运维工程师必须要掌握的技能
  2. Android 通过Socket 和服务器通讯
  3. Navigation + Tab Bar 常用组合框架
  4. linux nfs用的用户权限,权限 – Linux特定用户安装NFS
  5. java函数式编程例子_java函数式编程Lambda表达式的示例(一)
  6. python双目视觉三维重建代码_双目立体视觉的三维重建方法与流程
  7. 在c语言中输入三个数据类型,【C语言讲解】第二章:数据类型3
  8. 虚拟现实建模语言VRML
  9. matlab 程序运行报错 调试 不退出函数
  10. C# 打开指定文件夹下的excel