对于现代PHP应用来说,Nginx + PHP-FPM
的组合几乎是高性能架构的标配。但它们二者究竟是如何协同工作的呢?
本文将从Nginx的请求处理、FastCGI协议,再到PHP-FPM的进程管理,为你完整解析这个经典组合的工作流程。
第一步:Nginx的角色 - HTTP请求的接收与转发
首先,我们需要明确Nginx的核心角色。Nginx 是一款高性能的HTTP服务器和反向代理服务器。它的主要职责是:
- 接收客户端的HTTP请求
- 根据配置文件进行智能分发
当一个请求(例如 https://example.com/index.php
)到达Nginx时,它会执行以下操作:
- 匹配
server
块:通过域名、IP或端口找到对应的 server
配置。 - 匹配
location
块:在 server
块内,根据请求的URI(/index.php
)寻找最匹配的 location
规则。
对于PHP请求,通常会匹配到类似下面这样的 location
块:
location ~ \.php${
root /var/www/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
这段配置的核心指令是 fastcgi_pass 127.0.0.1:9000;
。
它告诉Nginx:“凡是匹配到以 .php
结尾的请求,都不要自己处理,而是将这个请求通过FastCGI协议,转发给监听在 127.0.0.1:9000
地址和端口的服务去处理。”
这里揭示了一个关键点:Nginx本身不执行PHP,它只是一个请求的“交通警察”。
补充知识:Nginx的静态模块Nginx的模块(如rewrite模块、proxy模块)是在编译时静态链接到Nginx二进制文件中的。这种设计使得Nginx在启动时无需像Apache那样动态加载模块,从而在启动速度和运行效率上具备一定优势。
第二步:FastCGI - 连接Nginx与PHP的桥梁
fastcgi_pass
指令中提到的 FastCGI 是一种通信协议。可以将其理解为Nginx和PHP之间沟通的“语言”。
- 定义:FastCGI是一个可伸缩、高速的接口,用于将Web服务器(如Nginx)与动态脚本语言(如PHP)的处理器连接起来。
- 优势:它解决了传统CGI模式“一个请求fork一个新进程”的性能瓶颈。FastCGI允许在一个或多个常驻进程中处理多个请求,大大降低了进程创建和销毁的开销。
所以,Nginx通过FastCGI协议,将请求的元信息(如HTTP头、请求参数等)打包,发送给127.0.0.1:9000
。现在的问题是,谁在那里监听呢?
第三步:PHP-FPM - PHP的专业进程管理器
在 127.0.0.1:9000
端口上监听的,正是 PHP-FPM (FastCGI Process Manager)。
PHP-FPM是PHP官方集成的、专门用于管理FastCGI进程的工具(自PHP 5.3.3起已内置)。它的主要职责是:
- 创建和管理PHP进程池
- 监听来自Web服务器的网络请求
- 将请求分配给空闲的PHP子进程处理
我们可以在PHP-FPM的配置文件(通常是 php-fpm.conf
或在 www.conf
中)找到与之对应的配置:
; The address on which to accept FastCGI requests.
; listen = /run/php/php8.1-fpm.sock ; 也可以是Unix socket方式
listen=127.0.0.1:9000 ; TCP/IP方式,与Nginx配置一致
PHP-FPM采用 Master/Worker 的多进程模型:
- Master主进程:负责监听端口、接收来自Nginx的请求,并根据配置管理Worker进程(如创建、销毁、重启)。
- Worker子进程:每个Worker进程都是一个独立的PHP解释器环境。它们被Master进程管理,平时处于“待命”状态,等待处理请求。当请求到来时,Master进程会将其交给一个空闲的Worker进程。
这种预先创建并复用Worker进程的模式(pre-fork
),正是FastCGI高性能的核心所在。
总结:一次完整的请求流程
现在,我们可以将整个流程串联起来:
- [客户端] 浏览器发起请求
https://example.com/index.php
。 - [Nginx] 接收到请求,匹配到
location ~ \.php$
规则。 - [Nginx -> PHP-FPM] Nginx通过FastCGI协议,将请求信息打包发送到
127.0.0.1:9000
。 - [PHP-FPM Master] Master进程监听到请求,选择一个空闲的Worker子进程来处理。
- [PHP-FPM Worker] Worker进程接收到请求,加载并执行
index.php
脚本。在执行过程中,它可能会连接数据库、读写缓存等。 - [PHP-FPM Worker -> Nginx] 脚本执行完毕后,Worker进程将生成的HTML内容或其他输出,通过FastCGI协议返回给Nginx。
- [Nginx -> 客户端] Nginx接收到来自PHP-FPM的响应内容,再将其作为标准的HTTP响应发送给客户端浏览器。
- [PHP-FPM] 处理完请求的Worker进程并不会立即销毁,而是会清理现场,继续等待下一个请求,实现了进程的复用。
通过这种清晰的分工与高效的协作,Nginx专注于处理网络连接和静态内容,而PHP-FPM则专注于执行PHP代码,共同构建了一个稳定、高性能的Web服务环境。