在 nginx 中使用 fastcgi_cache 可以缓存 php-fpm 生成的动态页面,显著降低后端负载并提升响应速度。以下是完整的配置方案和优化技巧。
核心配置架构
用户请求 → nginx → 检查缓存 → [命中] 直接返回缓存
↓
[未命中] → php-fpm → 生成页面 → 存入缓存 → 返回用户
基础配置
1. http 块(全局配置)
http {
# 定义缓存区
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=phpcache:100m max_size=1g inactive=60m use_temp_path=off;
# 缓存键定义(区分 uri 和参数)
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# 默认缓存时间
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 404 1m;
# 日志格式(可选,用于调试缓存命中率)
log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'cache:$upstream_cache_status';
}2. server/location 块(站点配置)
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php;
# php 请求处理
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
include fastcgi_params;
# ========== 缓存核心配置 ==========
# 启用缓存并指定缓存区
fastcgi_cache phpcache;
# 缓存条件:仅对登录用户以外的请求缓存
fastcgi_cache_bypass $cookie_session; # 有 session cookie 时不读缓存
fastcgi_no_cache $cookie_session; # 有 session cookie 时不写缓存
# 或者根据自定义 header 控制(如管理员后台不缓存)
fastcgi_cache_bypass $http_pragma;
fastcgi_no_cache $http_authorization;
# 缓存状态头(调试用,生产环境可移除)
add_header x-cache-status $upstream_cache_status;
# 缓存锁定(防止缓存失效时的并发穿透)
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 5s;
# 后台更新(旧缓存过期时,先返回旧数据,后台异步更新)
fastcgi_cache_background_update on;
# 使用 stale 缓存(后端故障时返回过期缓存)
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
}
# 静态文件不经过 php
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
access_log off;
}
}缓存控制策略详解
按 cookie 排除(用户登录状态)
# 如果有 wordpress_logged_in cookie 就不缓存(wordpress 场景)
fastcgi_cache_bypass $cookie_wordpress_logged_in;
fastcgi_no_cache $cookie_wordpress_logged_in;
# 多条件组合(任一满足即不缓存)
set $skip_cache 0;
if ($cookie_session) { set $skip_cache 1; }
if ($request_method = post) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($http_authorization) { set $skip_cache 1; }
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;按 url 排除(后台管理、api)
location ~ /wp-admin|/wp-login|/api/ {
fastcgi_cache off; # 完全禁用缓存
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include fastcgi_params;
}自定义缓存时间(按页面类型)
location ~ \.php$ {
fastcgi_cache phpcache;
# 首页缓存 5 分钟
if ($request_uri = /) {
set $cache_time 5m;
}
# 文章页缓存 1 小时
if ($request_uri ~ ^/post/) {
set $cache_time 1h;
}
# 默认 10 分钟
if ($cache_time = "") {
set $cache_time 10m;
}
fastcgi_cache_valid 200 $cache_time;
}缓存清理方案
方案 1:使用 ngx_cache_purge 模块(需编译安装)
# 编译时添加 --add-module=ngx_cache_purge
location ~ /purge(/.*) {
allow 127.0.0.1; # 仅允许本地访问
deny all;
fastcgi_cache_purge phpcache "$scheme$request_method$host$1";
}方案 2:脚本手动清理
#!/bin/bash
# /usr/local/bin/clear-php-cache.sh
cache_dir="/var/cache/nginx/fastcgi"
target="$1"
if [ -z "$target" ]; then
# 清理全部缓存
rm -rf ${cache_dir}/*
echo "all cache cleared"
else
# 根据 url 计算缓存文件路径(匹配 fastcgi_cache_key)
key="$scheme$request_method$host$target"
md5=$(echo -n "$key" | md5sum | awk '{print $1}')
level1=${md5: -1}
level2=${md5: -3:2}
rm -f "${cache_dir}/${level1}/${level2}/${md5}"
echo "cache for $target cleared"
fi
# 重载 nginx 使更改生效(或发送信号)
kill -hup $(cat /var/run/nginx.pid)生产环境优化配置
http {
# 缓存路径优化:ssd 建议用 levels=1:2,机械硬盘用 levels=1:2:3
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=phpcache:256m # 内存中存储 256mb 的键
max_size=10g # 磁盘最大 10gb
inactive=7d # 7 天未访问则清理
use_temp_path=off # 直接写入目标目录,减少 io
manager_files=10000 # 每次清理最多处理 10000 文件
manager_sleep=50ms # 清理间隔
manager_threshold=200ms; # 单次清理最大耗时
# 忽略后端设置的缓存控制头(强制按 nginx 配置缓存)
fastcgi_ignore_headers x-accel-expires expires cache-control set-cookie;
# 隐藏后端版本信息
fastcgi_hide_header x-powered-by;
fastcgi_hide_header server;
}
server {
location ~ \.php$ {
fastcgi_cache phpcache;
fastcgi_cache_valid 200 5m;
# 微缓存(microcache):极短时间的缓存,应对突发流量
fastcgi_cache_valid 200 1s; # 1 秒内相同请求直接返回缓存
# 缓存键增加设备类型(桌面/移动端分开缓存)
fastcgi_cache_key "$scheme$request_method$host$request_uri$http_user_agent";
}
}监控与调试
查看缓存命中率
# 查看缓存目录统计
find /var/cache/nginx/fastcgi -type f | wc -l
# 实时查看缓存状态头
curl -i http://example.com/page.php
# 检查响应头中的 x-cache-status: hit / miss / bypass / expired
# 分析日志统计命中率
awk '{print $nf}' /var/log/nginx/access.log | sort | uniq -c关键响应头说明
| 状态 | 含义 |
|---|---|
| hit | 缓存命中,直接返回 |
| miss | 缓存未命中,已写入新缓存 |
| bypass | 跳过缓存(如带有 cookie) |
| expired | 缓存过期,已重新获取 |
| updating | 缓存过期,但返回旧数据(后台更新中) |
| stale | 返回过期缓存(后端故障时) |
完整 wordpress 优化示例
fastcgi_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=wpcache:150m max_size=2g inactive=48h;
server {
set $skip_cache 0;
# 不缓存的条件
if ($request_method = post) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($cookie_woocommerce_items_in_cart) { set $skip_cache 1; } # woocommerce
if ($cookie_wordpress_logged_in) { set $skip_cache 1; }
if ($request_uri ~* "/wp-admin/|/wp-login|/cart|/checkout|/my-account") { set $skip_cache 1; }
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_cache wpcache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_lock on;
fastcgi_cache_use_stale updating error timeout;
add_header x-cache-status $upstream_cache_status;
}
}配置完成后,使用 nginx -t 检查语法,然后 systemctl reload nginx 生效。建议先用小流量测试,确认缓存逻辑符合预期后再全量上线。
到此这篇关于nginx中fastcgi_cache实现php页面缓存加速的文章就介绍到这了,更多相关nginx php页面缓存加速内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论