FastCGI介绍
什么是CGI
CGI的全称为“通用网关接口”(Common Gateway Interface),为HTTP服务器与其他机器上的程序服务通信交流的一种工具,CGI程序须运行在网络服务器上。传统CGI接口方式的主要缺点是性能较差,因为每次HTTP服务器遇到动态程序时都需要重新启动解析器来执行解析,后结果才会被返回给HTTP服务器。这在处理高并发访问时几乎是不可用的,因此就诞生了FastCGI。另外,传统的CGI接口方式安全性也很差,故而现在已经很少被使用了。
什么是FastCGI
FastCGI是一个可伸缩的,高速地在HTTP服务器和动态脚本语言间通信的接口(在Linux下,FastCGI接口即为socket,这个socket可以是文件socket,也可以是IP socket),主要优点是把动态语言和HTTP服务器分离出来。多数流行的HTTP服务器都支持FastCGI,包括Apache,Nginx和Lighttpd等。同时,FastCGI也被许多脚本语言所支持,例如当前比较流程的脚本语言PHP。FastCGI接口采用的是C/S架构,它可以将HTTP服务器和脚本解析服务器分开,同时还能在脚本解析服务器上启动一个或多个脚本来解析守护进程。当HTTP服务器遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求,或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。
FastCGI特点
- HTTP服务器和动态脚本语言间通信的接口或工具。
- 可把动态语言解析和HTTP服务器分离开。
- Nginx,Apache,Lighttpd,以及多数动态语言都支持FastCGI。FastCGI接口方式采用C/S结构,分为客户端(HTTP服务器)和服务器端(动态语言解析服务器)
- PHP动态语言服务器端可以启动多个FastCGI的守护进程(例如php-fpm(fcgi process mangement))
- HTTP服务器通过(例如Nginx fastcgi_pass)FastCGI客户端和动态语言FastCGI服务器端通 信(例如php-fpm)
Nginx FastCGI的运行原理
Nginx不支持对外部动态程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,为了调用CGI程序,还需要一个FastCGI的wrapper(可以理解为用于启动另一个程序的程序),这个wrappper绑定在某个固定的socket上,如端口或文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或外部程序处理脚本来读取返回的数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。
graph LR
%% 颜色定义
classDef client fill:#f5f5f5,stroke:#333;
classDef nginx fill:#ff9999,stroke:#b30000;
classDef fastcgi fill:#fff,stroke:#666;
classDef phpserver fill:#e6f3ff,stroke:#3366cc;
classDef fpm fill:#cc99ff,stroke:#6600cc;
classDef php fill:#99ccff,stroke:#0047b3;
classDef mysql fill:#dddddd,stroke:#666;
classDef config fill:#fff,stroke:#999,dashed;
%% 客户端部分
A[Client] -->|HTTP| B[Nginx]
class A client;
class B nginx;
%% FastCGI连接
B -->|"fastcgi_pass"| C[fastCGI]
class C fastcgi;
%% PHP服务器模块(独立虚线框)
subgraph "PHP Server"
C -->|"fastcgi_script_name"| D[php_fpm]
C -->|"fastcgi_script_name"| E[php_fpm]
D --> F[PHP Interpreter]
E --> F
G[php_fpm.conf] -.-> D
H[php.ini] -.-> E
end
class D,E fpm;
class F php;
class G,H config;
class phpserver phpserver;
%% 数据库部分(框外右侧)
F --> I[(MySQL)]
class I mysql;PHP.ini 配置文件解析
PHP.ini 是 PHP 的主要配置文件,用于控制 PHP 的各种行为和功能。以下是 PHP.ini 文件的主要配置项解析:
核心配置
语言选项
engine = On ; 启用 PHP 解析引擎
short_open_tag = Off ; 是否允许使用 <? 短标签
asp_tags = Off ; 是否允许 ASP 风格的 <% %> 标签
precision = 14 ; 浮点数显示精度资源限制
memory_limit = 128M ; 脚本可使用的最大内存量
max_execution_time = 30 ; 脚本最大执行时间(秒)
max_input_time = 60 ; 脚本解析输入数据的最大时间
post_max_size = 8M ; POST 数据最大尺寸
upload_max_filesize = 2M ; 上传文件最大尺寸错误处理
display_errors = Off ; 生产环境应关闭错误显示
log_errors = On ; 记录错误到日志
error_log = /path/to/log ; 错误日志路径
error_reporting = E_ALL ; 报告所有错误模块配置
数据库扩展
extension=mysqli.so ; MySQLi 扩展
extension=pdo_mysql.so ; PDO MySQL 驱动其他常用扩展
extension=gd.so ; GD 图像处理
extension=mbstring.so ; 多字节字符串支持
extension=openssl.so ; OpenSSL 支持性能优化
OPcache 配置
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60其他性能设置
realpath_cache_size = 4096K ; 真实路径缓存大小
realpath_cache_ttl = 120 ; 缓存生存时间(秒)安全配置
disable_functions = exec,system,passthru,shell_exec
allow_url_fopen = Off ; 禁用远程文件访问
expose_php = Off ; 隐藏 PHP 版本信息
session.cookie_httponly = 1 ; 仅 HTTP 访问 cookie
session.cookie_secure = 1 ; 仅 HTTPS 传输 cookie路径配置
include_path = ".:/php/includes" ; 包含文件搜索路径
upload_tmp_dir = /tmp ; 上传临时目录
session.save_path = "/tmp" ; Session 保存路径生产环境完整配置
;;;;;;;;;;;;;;;;;;;
;; 核心安全配置 ;;
;;;;;;;;;;;;;;;;;;;
expose_php = Off
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
disable_classes =
allow_url_fopen = Off
allow_url_include = Off
enable_dl = Off
;;;;;;;;;;;;;;;;;;
;; 资源限制配置 ;;
;;;;;;;;;;;;;;;;;;
max_execution_time = 30
max_input_time = 60
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 32M
max_file_uploads = 20
;;;;;;;;;;;;;;;;;;;
;; 错误处理配置 ;;
;;;;;;;;;;;;;;;;;;;
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
log_errors_max_len = 1024
ignore_repeated_errors = On
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
;;;;;;;;;;;;;;;;;;;
;; Session 配置 ;;
;;;;;;;;;;;;;;;;;;;
session.save_handler = files
session.save_path = "/var/lib/php/sessions"
session.use_strict_mode = 1
session.use_cookies = 1
session.use_only_cookies = 1
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Strict"
session.gc_maxlifetime = 1440
session.sid_length = 128
session.sid_bits_per_character = 5
session.hash_function = "sha256"
;;;;;;;;;;;;;;;;;;;
;; OPcache 配置 ;;
;;;;;;;;;;;;;;;;;;;
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=0
opcache.validate_timestamps=0 ; 生产环境关闭
opcache.save_comments=0
opcache.consistency_checks=0
;;;;;;;;;;;;;;;;;;;
;; FPM 相关配置 ;;
;;;;;;;;;;;;;;;;;;;
[PHP]
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
request_terminate_timeout = 30s
;;;;;;;;;;;;;;;;;;;;
;; 数据库连接配置 ;;
;;;;;;;;;;;;;;;;;;;;
mysqli.default_port = 3306
mysqli.allow_local_infile = Off
mysqli.allow_persistent = Off
pdo_mysql.default_socket=
;;;;;;;;;;;;;;;;;;;;
;; 性能优化配置 ;;
;;;;;;;;;;;;;;;;;;;;
realpath_cache_size=4096K
realpath_cache_ttl=600
zend.exception_ignore_args = On
zend.exception_string_param_max_len = 0
;;;;;;;;;;;;;;;;;;;;
;; 文件上传配置 ;;
;;;;;;;;;;;;;;;;;;;;
file_uploads = On
upload_tmp_dir = /tmp/php_uploads
;;;;;;;;;;;;;;;;;;;;
;; 时区配置 ;;
;;;;;;;;;;;;;;;;;;;;
date.timezone = "Asia/Shanghai"PHP-FPM配置
www.conf 核心配置解析
[www]
; ----------------------------
; 进程身份配置
; ----------------------------
user = www-data ; 进程运行用户(需与Nginx用户一致)
group = www-data ; 进程运行组
listen.owner = www-data ; Socket文件所有者
listen.group = www-data ; Socket文件所属组
listen.mode = 0660 ; Socket文件权限(需Nginx可读写)
; ----------------------------
; 进程池管理策略
; ----------------------------
pm = dynamic ; 动态进程管理(生产环境推荐)
pm.max_children = 50 ; 最大子进程数(根据内存计算:总内存/单个进程内存)
pm.start_servers = 10 ; 启动时创建的进程数(建议 = pm.min_spare_servers)
pm.min_spare_servers = 10 ; 最小空闲进程数
pm.max_spare_servers = 20 ; 最大空闲进程数
pm.max_requests = 500 ; 单个进程处理请求数后重启(防内存泄漏)
; ----------------------------
; 性能与资源控制
; ----------------------------
request_terminate_timeout = 30s ; 单请求超时时间(需≤Nginx的fastcgi_read_timeout)
request_slowlog_timeout = 5s ; 慢请求日志阈值
slowlog = /var/log/php-fpm/slow.log ; 慢日志路径
rlimit_files = 65535 ; 文件描述符限制
rlimit_core = 0 ; 禁止生成core dump
; ----------------------------
; 连接与Socket配置
; ----------------------------
listen = /run/php/php8.2-fpm.sock ; Unix Socket路径(比TCP更快)
; listen = 127.0.0.1:9000 ; 备用TCP端口配置
listen.backlog = 511 ; 等待连接队列长度(建议2^n-1)
listen.allowed_clients = 127.0.0.1 ; 仅允许本地连接
; ----------------------------
; 日志与调试
; ----------------------------
access.log = /var/log/php-fpm/access.log ; 请求访问日志
catch_workers_output = yes ; 捕获进程输出到错误日志
php_admin_value[error_log] = /var/log/php-fpm/error.log ; 错误日志路径
php_admin_flag[log_errors] = on ; 强制开启错误日志
; ----------------------------
; 安全加固配置
; ----------------------------
security.limit_extensions = .php ; 仅允许解析.php后缀
php_flag[display_errors] = off ; 覆盖php.ini的错误显示设置
php_admin_value[doc_root] = /var/www/html ; 限制文件根目录关键配置说明
进程管理策略
dynamic模式根据流量自动调整进程数,计算公式:单个进程内存 ≈ PHP脚本平均内存 × 1.2 最大进程数(pm.max_children) ≈ (总内存 - 系统预留) / 单个进程内存- 示例:若PHP脚本平均消耗30MB,4GB内存服务器建议设置为:
pm.max_children = (4096MB - 512MB) / (30MB × 1.2) ≈ 100
Socket vs TCP
- Unix Socket(默认)比TCP少协议开销,性能提升约15%
- 若需跨服务器通信,改用:ini
listen = 9000 listen.allowed_clients = 192.168.1.100 ; Nginx服务器IP
安全最佳实践
- 通过
security.limit_extensions防止恶意上传文件解析 - 使用
php_admin_value强制覆盖危险配置(如disable_functions)
- 通过
与Nginx的协同配置
nginxlocation ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 必须与www.conf的listen一致 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_read_timeout 35s; # 需 > request_terminate_timeout }
生产环境建议
监控指标
bash# 查看活跃进程数 ps aux | grep php-fpm | grep -v grep | wc -l # 检查慢日志 tail -f /var/log/php-fpm/slow.log调优方向
- 高并发场景:增加
pm.max_children和listen.backlog - 内存优化:降低
pm.max_requests值(如300)预防内存泄漏 - 安全审计:定期检查
access.log异常请求
- 高并发场景:增加
故障排查命令
bash# 验证配置 php-fpm -t # 平滑重启 sudo systemctl reload php-fpm
请根据实际服务器硬件(CPU/内存)和业务流量调整数值,配置后需重启php-fpm生效。
