PHP

FastCGI 协议

深入理解nginx、php通讯机制 FastCGI 协议

Posted by Angkee on July 26, 2018

nginx 和 php 通讯主要通过 FastCGI 通讯协议。

说起 FastCGI,需要先解释一下 CGI,通用网关接口 (Common Gateway Interface),是 Web Server 与后台语言交互的协议,有了这个协议,开发者可以使用任何语言处理 Web Server 发来的请求,动态的生成内容。

工作流程:当 Web 服务器的 CGI 进程接受到 HTTP 请求,通过标准输入转发到 PHP 程序,PHP 处理完之后,Web 服务器的 CGI 从标准输出读取返回数据,并转换为 HTTP 响应消息格式,最后 Web 服务器关闭 CGI 这个进程。

CGI 程序的缺陷:每一次的用户请求,都会 fock 出一个 CGI 子进程、销毁子进程、一系列的 I/O 降低了网络的吞吐量、会造成不必要的资源浪费,而且在大并发的场景下,会有很大的性能问题。

FastCGI 不同于 CGI,FastCGI 采用常驻内存的方式,每一个请求处理和结束的过程中,始终常驻进程中,不需要 fock 子进程,降低了资源的开销、每个请求平均响应时间。

Web 服务器和 FastCGI 交互过程:

  1. Web 服务器启动时载入初始化 FastCGI 执行环境 。 例如 nginx ngx_http_fastcgi_module
  2. FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程并等待来自 Web 服务器的连接。启动 FastCGI 进程时,可以配置以 ip 和 UNIX 域 socket 两种方式启动
  3. 当客户端请求到达 Web 服务器时, Web 服务器将请求采用 socket 方式转发到 FastCGI 主进程,FastCGI 主进程选择并连接到一个 CGI 解释器(PHP-FPM),Web 服务器将 CGI 环境变量和标准输入发送到 FastCGI 子进程
  4. FastCGI 子进程完成处理后将标准输出和错误信息从同一 socket 连接返回 Web 服务器。当 FastCGI 子进程关闭连接时,请求便处理完成
  5. FastCGI 子进程接着等待并处理来自 Web 服务器的下一个连接

Nginx 中 FastCGI 转发请求的配置:

pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
   root           html;
   fastcgi_pass   127.0.0.1:9000;
   fastcgi_index  index.php;
   fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
   include        fastcgi_params;
}

PHP-FPM

PHP-FPM 是 FastCGI 进程管理器(PHP FastCGI Process Manager),由两种进程组成,一个 Master 进程和多个 Worker 进程。Master 进程负责监听端口,接收来自 Web 服务器的请求,然后指派具体的 Worker 进程处理请求;worker 进程则一般有多个 (依据配置决定进程数),每个进程内部都嵌入了一个 PHP 解释器,用来执行 PHP 代码。

Nginx 服务器无法直接与 FastCGI 服务器进行通信,需要启用 ngx_http_fastcgi_module 模块进行代理配置,才能将请求发送给 FastCGI 服务。