Nginx server块不支持动态切换PHP-FPM池,需按请求特征(路径、参数等)精准路由至预设池;常用方式为嵌套location按路径分流或map指令按参数映射,关键要确保监听地址互斥且SCRIPT_FILENAME路径正确。

Nginx 的 server 块本身不支持“动态切换” PHP-FPM 池,但可通过请求特征(如路径、查询参数、域名)将不同 PHP 请求精准路由到多个已预设的 PHP-FPM 监听池,从而实现逻辑上的“动态解析”。关键在于路由控制 + 池隔离 + 参数对齐。
按 URL 路径分发到不同 PHP-FPM 池
适用于同一域名下按子目录区分 PHP 版本或配置的场景(例如 /app74/ 用 PHP 7.4,/app82/ 用 PHP 8.2):
- 在
server块中为每个子路径定义独立location块 - 每个
location设置专属root或alias,并嵌套location ~ \.php$处理 PHP 请求 - 各自指定不同的
fastcgi_pass(如127.0.0.1:9074、unix:/run/php/php8.2-fpm.sock) -
SCRIPT_FILENAME必须使用$request_filename(配合alias)或$document_root$fastcgi_script_name(配合root),避免路径拼接错误
示例:
location /app74/ {
alias /var/www/app74/;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9074;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}
location /app82/ {
alias /var/www/app82/;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}用 map 指令根据请求参数分流
适合轻量级条件路由,比如通过 ?phpver=82 强制走特定版本:
立即学习“PHP免费学习笔记(深入)”;
- 在
http块顶部定义map,将变量(如$arg_phpver)映射为后端地址 -
server中统一用fastcgi_pass $php_backend,不再硬编码 - 所有
fastcgi_param仍需完整保留(尤其是SCRIPT_FILENAME)
示例:
http {
map $arg_phpver $php_backend {
default "127.0.0.1:9000";
82 "unix:/run/php/php8.2-fpm.sock";
74 "127.0.0.1:9074";
}
server {
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass $php_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}确保 PHP-FPM 池已就绪且互不冲突
路由生效的前提是后端监听池真实可用:
- 每个池必须在独立配置文件中(如
/etc/php/8.2/fpm/pool.d/app82.conf)启用,且listen地址不重叠(端口或 socket 文件唯一) - 各池的
user/group权限需能读取对应代码目录,pm = dynamic等模式配置完整(pm.max_children、pm.start_servers等五项缺一不可) - 修改池配置后必须执行
sudo systemctl reload php8.2-fpm(不是restart),并用sudo php-fpm8.2 -t验证语法
SCRIPT_FILENAME 和 root/alias 的匹配要点
这是 502 错误最常见原因:
- 若
location使用alias,PHP 脚本的绝对路径由$request_filename给出,不能用$document_root - 若
location使用root,则$document_root必须指向该 location 下 PHP 文件所在物理路径的上级目录 - 推荐统一把
root放在server级,各子location用alias明确映射,减少歧义
不复杂但容易忽略。



















