Nginx + PHP-FPM 配置
Nginx 与 PHP-FPM 的组合是 PHP 应用最常见的部署架构。Nginx 作为反向代理和静态文件服务器,负责处理 HTTP 请求、负载均衡和缓存;PHP-FPM 作为 PHP 进程管理器,负责执行 PHP 代码。本节将详细讲解 Nginx 与 PHP-FPM 的集成配置、优化参数、负载均衡、缓存配置以及 HTTPS 设置。
前置知识
阅读本节前,建议先了解:PHP-FPM 调优、Docker 部署
基础概念
Nginx + PHP-FPM 通信方式
text
方式一:Unix Socket(推荐)
Client → Nginx → unix:/var/run/php-fpm/www.sock → PHP-FPM
方式二:TCP Socket
Client → Nginx → 127.0.0.1:9000 → PHP-FPM
方式三:远程 TCP
Client → Nginx → 10.0.0.1:9000 → PHP-FPM (远程服务器)基础配置
fastcgi_params 配置
nginx
# /etc/nginx/fastcgi_params
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param REDIRECT_STATUS 200;基本 Server 配置
nginx
server {
listen 80;
server_name example.com www.example.com;
root /var/www/app/public;
index index.php index.html;
charset utf-8;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 禁止访问隐藏文件
location ~ /\.(?!well-known) {
deny all;
access_log off;
log_not_found off;
}
# 主要路由
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP 处理
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# FastCGI 优化
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_busy_buffers_size 32k;
fastcgi_read_timeout 300;
fastcgi_intercept_errors on;
}
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2?|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
log_not_found off;
}
# 健康检查端点
location = /health {
access_log off;
return 200 "OK";
add_header Content-Type text/plain;
}
# 访问日志和错误日志
access_log /var/log/nginx/app_access.log;
error_log /var/log/nginx/app_error.log;
}Upstream 与负载均衡
多个 PHP-FPM 实例负载均衡
nginx
# Upstream 定义
upstream php_backend {
# 加权轮询(默认策略)
server unix:/var/run/php-fpm/app_1.sock weight=3;
server unix:/var/run/php-fpm/app_2.sock weight=2;
server unix:/var/run/php-fpm/app_3.sock weight=1;
# 备用服务器
# server unix:/var/run/php-fpm/app_backup.sock backup;
# 健康检查参数
keepalive 32;
keepalive_timeout 60s;
}
# 最少连接策略
upstream php_backend_least_conn {
least_conn;
server 10.0.0.1:9000;
server 10.0.0.2:9000;
server 10.0.0.3:9000;
}
# IP Hash 策略(会话保持)
upstream php_backend_ip_hash {
ip_hash;
server 10.0.0.1:9000;
server 10.0.0.2:9000;
}
server {
listen 80;
server_name example.com;
location ~ \.php$ {
fastcgi_pass php_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}Keepalive 连接复用
nginx
upstream php_fpm {
server unix:/var/run/php-fpm/www.sock;
keepalive 32; # 每个 worker 的空闲 keepalive 连接数
}
server {
location ~ \.php$ {
fastcgi_pass php_fpm;
fastcgi_keep_conn on; # 启用 keepalive
include fastcgi_params;
}
}缓存配置
FastCGI 缓存
nginx
# 定义缓存区域
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=PHP_CACHE:100m
max_size=1g
inactive=60m
use_temp_path=off;
server {
listen 80;
server_name example.com;
root /var/www/app/public;
# 启用 FastCGI 缓存
set $skip_cache 0;
# POST 请求不缓存
if ($request_method = POST) {
set $skip_cache 1;
}
# 带查询参数的请求不缓存
if ($query_string != "") {
set $skip_cache 1;
}
# 带有特定 Cookie 的请求不缓存
if ($http_cookie ~* "session_id|auth_token") {
set $skip_cache 1;
}
# 登录用户不缓存
if ($request_uri ~* "/admin|/login|/api") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 缓存配置
fastcgi_cache PHP_CACHE;
fastcgi_cache_valid 200 301 302 10m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 5s;
# 缓存状态头(调试用)
add_header X-FastCGI-Cache $upstream_cache_status;
}
}HTTPS 配置
Let's Encrypt SSL 配置
nginx
# HTTP → HTTPS 重定向
server {
listen 80;
server_name example.com www.example.com;
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/app/public;
# SSL 证书
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 优化参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# 其余配置...
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTPS on;
}
}性能优化
全局优化配置
nginx
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log warn;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time';
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
}实战示例
API 专用 Nginx 配置
nginx
server {
listen 80;
server_name api.example.com;
root /var/www/app/public;
# 速率限制
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;
# 客户端请求体大小限制
client_max_body_size 20m;
# API 路由
location / {
limit_req zone=api_limit burst=20 nodelay;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
limit_req zone=api_limit burst=20 nodelay;
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# API 超时设置
fastcgi_read_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
}
access_log /var/log/nginx/api_access.log main;
}注意事项
安全配置
- 禁用 server_tokens 防止版本泄露
- 配置合理的 client_max_body_size
- 设置 security headers(X-Frame-Options、CSP 等)
- 限制访问敏感目录(.env、storage 等)
最佳实践
- 使用 Unix Socket:比 TCP 性能更好
- 启用 Keepalive:减少连接建立开销
- 开启 Gzip:减少传输数据量
- 配置 FastCGI 缓存:减少 PHP 执行次数
- 设置合理的超时:避免慢请求阻塞 worker
- 分离静态文件:Nginx 直接处理静态文件,不走 PHP
- 日志分析:使用合适的日志格式便于后续分析
下一节
继续学习:日志管理