0%

cgi/fast-cgi/php-cgi/php-fpm

每种动态语言(PHP,Python 等)的代码文件需要通过对应的解析器才能被服务器识别,而 CGI 协议就是用来使解释器与服务器可以互相通信。PHP 文件在服务器上的解析需要用到 PHP 解释器,再加上对应的 CGI 协议,从而使服务器可以解析到 PHP 文件。

一、概念

  1. CGI(COMMON GATEWAY INTERFACE)公共网关接口,它的作用就是帮助服务器与web编程语言通信,是为了保证web server传递过来的数据是标准格式的,方便CGI程序(如php-cgi)的编写者。

    • 如果一个静态请求如xxx/index.html或/image.png等,那么web server会去文件系统中找到这个文件并发送给浏览
    • 如果一个动态请求如xxx/index.php或/index.jsp等,nginx会根据配置文件将这个请求简单处理后交给相应的解析器(如PHP)
    • 假如请求的是index.php,nginx会传哪些数据给PHP解析器呢?url要有吧,查询字符串也得有吧,POST数据也要有,HTTP Header不能少吧等等。CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。
    • 当web server收到/index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以CGI规定的格式返回处理后的结果,退出进程。web server再把结果返回给浏览器。
  2. fast-cgi是用来提高CGI程序性能的,那么CGI程序的性能问题在哪呢?即上文中”PHP解析器会解析php.ini文件,初始化执行环境”这个过程。

    • 传统的cgi协议在每次连接请求时都会开启一个进程进行处理,处理完毕会关闭该进程。下次连接请求又要再次开启一个进程进行处理,cgi是一个进程只能处理一个请求,有多少个连接就有多少个cgi进程,过多的进程会消耗资源和内存。
    • fast-cgi则是一个进程可以处理多个请求。
    • fast-cgi具体是怎么做的呢?首先,fast-cgi会先启一个master进程,解析配置文件,初始化执行环境;然后再启动多个worker进程。当请求过来时master会传递给一个worker,然后立即可以接受下一个请求,这样就避免了重复的工作,效率自然是高。当worker进程不够用时,master进程可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些。
    • fastcgi只是一种协议(就像http协议一样,apache对它的实现是httpd,nginx对它的实现就叫nginx),不是进程。
  3. php-cgi:php的解释器,php-cgi是php提供给web serve也就是http前端服务器的cgi协议接口程序。

    • 当每次接到http前端服务器的请求都会开启个php-cgi进程进行处理,开启的php-cgi的过程中会先要重载配置,数据结构以及初始化运行环境。如果更新了php配置,那么就需重启php-cgi才能生效。
    • php-cgi只是个CGI程序,本身只能处理请求返回结果,不会管理进程,所以就出现了一些能够调度php-cgi进程的程序,比如由lighthttpd分离出来的spawn-fcgi,再比如php-fpm。
  4. php-fpm全称为PHP FastCGI Process Manager,是一个实现了fast-cgi的程序,被PHP官方收了。它不会像php-cgi一样每次连接都会重新开启一个程,处理完请求又关闭这个进程,而是允许一个进程对多个连接进行处理,处理完不会立即关闭这个进程,而是会接着处理下一个连接。

    • 它可以说php-cgi的一个管理程序,是对php-cgi的改进。
    • php-fpm会开启多个php-cgi程序,并且php-fpm常驻内存,每次web server服务器发连接过来的时候,php-fpm将连接信息分配给下面其中的一个子程序php-cgi进行处理,处理完毕这个php-cgi并不会关闭,而是继续等待一个连接,这也是fast-cgi加速的原理。
    • 由于php-fpm是多进程的,而一个php-cgi基本消耗7-25M内存,因此如果连接过多就会导内存消耗过大,引发一些问题,例如nginx里的502错误。

二、参考

  1. 简单说明CGI和动态请求是什么
  2. PHP-FPM以及php-cgi, fast-cgi,以及与nginx的关系

三、备注

  1. cgi:它是一种协议。通过cgi协议,web server可以将动态请求和相关参数发送给专门处理动态内容的应用程序。
  2. fastcgi:也是一种协议,只不过是cgi的优化版。cgi的性能较烂,fastcgi则在其基础上进行了改进。
  3. php-cgi:fastcgi是一种协议,而php-cgi实现了这种协议。不过这种实现比较烂。它是单进程的,一个进程处理一个请求,处理结束后进程就销毁。
  4. php-fpm:是对php-cgi的改进版,它直接管理多个php-cgi进程/线程。也就是说,php-fpm是php-cgi的进程管理器,因此它也算是fastcgi协议的实现。
  5. cgi进程/线程:在php上,就是php-cgi进程/线程,专门用于接收web server的动态请求,调用并初始化zend虚拟机。
  6. cgi脚本:被执行的php源代码文件。
  7. zend虚拟机:对php文件做词法分析、语法分析、编译成opcode,并执行。最后关闭zend虚拟机。
  8. cgi进程/线程和zend虚拟机的关系:cgi进程调用并初始化zend虚拟机的各种环境。