「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
web server 指的是 apache、nginx等。
应用程序 指的是 PHP、PERL、TCL等。
CGI程序指的是使用CGI协议的 PHP、PERL、TCL等。
由于web server并不能直接运行PHP、PERL的文件,无法直接与应用程序直接通信,因此有了CGI。
CGI
CGI定义
CGI 全称是公共网关接口(Common Gateway Interface),CGI是应用程序(CGI程序)与 Web server 之间的接口通信标准。注意,它不是一门编程语言,而是一种协议。CGI 可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如 PHP, Perl, Tcl 等。
CGI工作方式
web server 处理静态文件只需要找到文件,然后返回给浏览器就可以。但如果是一个动态脚本请求,就需要通过CGI协议规定接受数据的格式。创建一个进程,然后解析配置文件,初始化执行环境,然后再处理请求,处理完之后把数据返回给web server,最后销毁进程。但是,CGI程序是运行在独立的进程中,对每一个请求都会执行上述过程。创建一个进程,解析配置文件,处理完后再销毁进程。这种方式实现虽然容易,但是可见效率是非常差的。对于大量的请求,进程的频繁创建和销毁使得服务器性能大大下降(这是CGI最让人诟病的for-and-execute模式)。
FastCGI
FastCGI定义
FastCGI也是一个协议,不过是对CGI做了优化,提高了性能。
FastCGI工作方式
FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次。每一个请求执行完后,不会再销毁进程,而是等待下一个请求。
PHP-CGI
上面说了不管CGI还是FastCGI,都是一个协议。
PHP-CGI是CGI和FastCGI在PHP中的实现。
不过PHP-CGI有两个明显的缺点。
- 修改PHP的配置文件php.ini后,需要重启PHP-CGI才能生效,不能平滑重启。
- 杀死PHP-CGI进程后,并不会重新创建进程,PHP就不能运行了。
PHP-FPM
PHP-FPM 是 FastCGI 进程管理器。
在PHP的新版本中,PHP-FPM已经是内置的进程管理器。使用--enalbe-fpm这个编译参数即可。
相对于PHP-CGI来说,PHP-FPM可以实现平滑启动,并且杀死进程后,会有守护进程自动重启。
PHP-FPM的实现就是创建一个master进程,在master进程中创建并监听socket,然后fork出多个子进程,这些子进程各自accept请求,子进程的处理非常简单,它在启动后阻塞在accept上,有请求到达后开始读取请求数据,读取完成后开始处理然后再返回,在这期间是不会接收其它请求的,也就是说fpm的子进程同时只能响应一个请求,只有把这个请求处理完成后才会accept下一个请求,这一点与nginx的事件驱动有很大的区别,nginx的子进程通过epoll管理套接字,如果一个请求数据还未发送完成则会处理下一个请求,即一个进程会同时连接多个请求,它是非阻塞的模型,只处理活跃的套接字。
fpm的master进程与worker进程之间不会直接进行通信,master通过共享内存获取worker进程的信息,比如worker进程当前状态、已处理请求数等,当master进程要杀掉一个worker进程时则通过发送信号的方式通知worker进程。
fpm可以同时监听多个端口,每个端口对应一个worker pool,而每个pool下对应多个worker进程,类似nginx中server概念。
以上PHP-FPM的介绍来自php7内核剖析
PHP-CGI实现的是FastCGI协议。
总结
CGI和FastCGI只是一个协议,FastCGi是CGI优化后的,它们并不是只针对PHP的。
PHP-CGI和PHP-FPM的关系
它们都是对CGI和FastCGI的具体实现。由于PHP-CGI有一些缺点和没有进程调度,所以有了PHP-FPM。
PHP-FPM是调用PHP-CGI吗?
需要根据版本分开说,在PHP5.4之前,PHP-FPM属于第三方编译,是管理器,PHP-CGI是解释器,PHP-FPM需要依赖于PHP-CGI执行。
PHP5.4版本开始,PHP-FPM是PHP内置,不在依赖于PHP-CGI,PHP-FPM既是管理器,又是解释器。