cgi、fastcig、phpcgi、php-fpm的关系和区别

从开始学习php编程,就不断的接触到cgi、fastcig、phpcgi、php-fpm的概念,但平时开发更多的是注重业务层面的代码,而没有特别的去关注这些比较底层的实现和原理,但如果要在编程界持续提升,只会业务上的编程,显然不足以体现自己的优秀,面试中也经常被问到一些服务的底层实现原理,虽然看上去和工作中的开发关系不大,但面试官主要也是考察你的学习能力也对知识的广度掌握。

今天,就我理解的cgi、fastcig、phpcgi、php-fpm的关系和区别,做一个浅显易懂的笔记,不要长篇大论,只抓其中重点。

一、CGI

概念: CGI是Common Gateway Interface的简写,意思是“通用网管接口”,用于处理WebServer和后端程序之间的一种通信标准,也可以说是一种通信协议。它制定了包括URL、查询字符串、POST数据,HEADER等的数据传输标准,使得web服务器(nginx、apache、lighttpd)和后端程序如php等之间的数据沟通成为可能。

原理:每次从客户端(浏览器)发起一个请求(请求index.php)时,websserver知道这不是一个静态资源,而是需要交给动态语言处理,因此就会启动对应语言的CGI服务(生产环境实际上不是CGI,下面再讲),对应语言的CGI服务(如PHP解释器)会初始化相应的环境、配置,然后处理对应业务逻辑程序,最后把处理后的结果按照CGI规定的格式返回给webserver,然后退出进程,webserver再把结果交给客户端。这样就完成了一次请求,也实现了一次CGI的服务过程。简单浓缩为一张图如下:

image.png

缺点:在每次客户端发起请求,将数据处理完成之后,CGI进程是会退出的,因此他最大的不足就是高并发时的性能较差

           详细来说就是: fork-and-execute模式(每次HTTP服务器遇到动态请求时都需要重新启动脚本解析器来解析php.ini,重新载入全部DLL扩展并重初始化全部数据结构,然后把结果返回给HTTP服务器)

应用场景: 因为上面说过他就是一个fork-and-execute模式,所以他更多的是用来开发调试,生产环境基本不采用

二、FastCGI

概念:从名称可以看出,他和CGI好像有很多相同之处,没错,他可以理解为是CGI的升级版本,全写为:Fast Common Gateway Interface,即快速通用网关接口,主要是用来提高cgi程序的性能,它也是一种提供web服务和后端程序交互的一种协议。fastcgi的实现,能够减少每次初始化和销毁的开销,从而支持更多的请求同时处理,以提高程序的并发访问。同样fastcgi也需要有对应的语言程序来实现。

原理:fastcgi是随着webserver服务的启动一起启动的,如(apache的module,对php而言,就是phpx_module,nginx的php-fpm,IIS的ISAPI等),它在启动时,就去加载配置文件(如php.ini),进行初始化,启动多个解释器进程(如php的php-cgi进程),当有请求从客户端发出,webserver识别为动态资源,就通过fastcgi选择一个其子进程进行处理(如php脚本,就会选择一个php-cgi)处理完毕后,再按照fastcgi的数据格式返给webserver,然后关闭子进程或处于等待模式。webserver再将处理好的数据发送到客户端,完成一次请求。简单画下示意图就是:

image.png

优点:1. 因为fastcgi是c/s架构,意思是类似于客户端请求服务端的模式,因此可以将fastcgi独立部署于专门的机器上,例如nginx中的配置有这么一项

location ~ [^/]\.php(/|$)
{
            fastcgi_pass  unix:/tmp/php-cgi.sock;   // 这一项可配置fastcgi的具体服务器地址
            fastcgi_index index.php;
            include fastcgi.conf;
}

            如果在 A服务器上(192.168.1.2)部署的是webserver(nginx),在B服务器上(192.168.1.100)部署了fastcgi服务,那么A服务器上的nginx中的fastcgi的转发地址可以配置为:192.168.1.100:9000

            这样就可以将静态资源全部交给A服务器,而动态资源交给其他服务器处理,互相独立运行

            2. fastcgi程序在修改了配置文件后可以实现平滑重启(但这必须依赖于进程管理器,如php的 php-fpm)

            3. 最重要的一点,为何fastcgi可以提高并发处理的能力,这得益于他是一个常驻内存的服务进程,即long-live cgi,他每次启动时,就会初始化多个子进程,并且保持监听,而php-fpm对其进行管理,当重启php-fpm时,会重新启动最新的进程,老的进程会被逐一干掉。

缺点:上面提到它是一个多进程的常驻内存的模式,因此他会比CGI更加消耗内存,所以在配置子进程数量时,需要考虑服务器的内存限制,防止过量。

三、php-cgi

概念: php-cgi我理解的应该是使用php对fastcgi的具体实现,php-cgi的具体实现参见phpcgi的具体实现,核心是使用socket编程实现一个同产品协议,并在启动时执行socket监听。

特点: 通过对上述phpcgi的具体实现的了解,php-cgi因为一启动便一直处于监听状态,可以理解为就是常驻内存的运行,因此改动php.ini配置时,必须重启才能生效,而无法平滑重启,同时直接杀死php-cgi进程,php就不能够在运行了

四、php-fpm

概念:PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,在./configure的时候带 –enable-fpm参数即可开启PHP-FPM

原理:当重启php-fpm时,它会启动新的worker用新的配置,业务请求会转发到新的worker上,从而导到平滑重启的目的

php的运行模式

php目前比较常见的五大运行模式:包括cli、cgi 、fast-cgi、isapi、apache模块的DLL 

1. cli模式就是我们平常在命令行直接执行 php index.php的方式,所以也被称为命令行模式

2. cgi模式,这个在上面已经解释过,一般用作开发调试使用,因为无需重启php进程也能用到最新的php配置,生产环境基本不用,因为无法处理高并发请求

3. fastcgi模式,这个是现在主流的方式

4. isapi模式,是微软提供的一套面向Internet服务的API接口,一个ISAPI的DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个DLL里设置多个用户请求处理函数,此外,ISAPI的DLL应用程序和www服务器处于同一个进程中,效率要显著高于CGI。(由于微软的排他性,只能运行于windows环境)

5. apache模块模式,此运行模式可以在Linux和windows环境下使用Apache,他们的共同点都是用 LoadModule 来加载相关模块,有两种类型

    a. Apache调用php的相关模块(php5_module),也就是把php作为apache的一个子模块来运行。当通过web访问php文件时,apache就会调用php5_module通过sapi将数据传给php解析器来解析php代码,整个过程如下图:

image.png

所以,以上的apache调用php执行的过程如下:

apache -> httpd -> php5_module -> sapi -> php

    b. mod_cgi模式,这种方式和php-cgi就差不多,需要单独启动进程来做通信

参考文章:

CGI、FastCGI和PHP-FPM关系图解:https://www.awaimai.com/371.html

关于CGI 和 PHP-FPM需要弄清的:http://www.cleey.com/blog/single/id/848.html

浅谈PHP fastcgi和php-fpm:https://www.jianshu.com/p/d095cbcbcf1b

php五大运行模式CGI,FAST-CGI,CLI,ISAPI,APACHE模式浅谈:https://www.cnblogs.com/XACOOL/p/5619650.html

Related Post

发表评论

电子邮件地址不会被公开。 必填项已用*标注