如何通过Nginx FastCGI缓存由PHP生成的404响应?
实现Nginx FastCGI缓存404跳转后的PHP生成图片
针对你的需求——让Nginx通过FastCGI缓存由error_page 404 = /url_rewriting.php跳转后PHP生成的图片,我们分Nginx配置调整和PHP代码优化两部分来落地:
第一步:配置Nginx的FastCGI缓存规则
首先要让Nginx识别并缓存这个特殊场景下的响应,核心是定义缓存存储、匹配跳转后的请求并启用缓存:
- 全局/Server级缓存基础配置
# 指定缓存存储路径、内存缓存区、有效期等 fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=PHP_IMAGE_CACHE:10m max_size=10g inactive=7d use_temp_path=off; # 设置需要缓存的响应状态码:因为你用了`error_page 404 = /...`,跳转后返回的是200状态码,所以重点缓存200 fastcgi_cache_valid 200 7d; # 可选:如果保留404状态码(去掉error_page里的等号),需要添加404到缓存列表 # fastcgi_cache_valid 404 1h; # 生成唯一缓存键:包含请求协议、方法、域名、完整请求路径(含路径参数),确保不同参数的图片能独立缓存 fastcgi_cache_key "$scheme$request_method$host$request_uri";
- 针对url_rewriting.php的缓存启用
server { # 你的其他server配置(监听端口、域名等)... # 404跳转规则保持不变 error_page 404 = /url_rewriting.php; location = /url_rewriting.php { fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 替换成你的PHP-FPM实际路径 fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 启用缓存 fastcgi_cache PHP_IMAGE_CACHE; # 允许通过Cache-Control请求头跳过缓存(方便调试) fastcgi_cache_bypass $http_cache_control; fastcgi_no_cache $http_cache_control; # 缓存失效时允许返回旧缓存(避免请求雪崩) fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; # 可选:添加缓存状态头,方便调试查看是否命中缓存 add_header X-Cache $upstream_cache_status; } }
第二步:优化PHP代码的缓存控制头
PHP生成图片时需要输出正确的缓存头,告诉Nginx这个响应可以被缓存,同时保证图片输出的完整性:
在你的图片生成逻辑前添加以下头部代码:
// 设置缓存有效期(和Nginx的fastcgi_cache_valid保持一致,这里是7天) header("Cache-Control: public, max-age=604800"); header("Expires: " . gmdate("D, d M Y H:i:s", time() + 604800) . " GMT"); // 输出对应图片类型的Content-Type(比如PNG用image/png,JPG用image/jpeg) header("Content-Type: image/png"); // 你的现有参数提取与图片生成逻辑 if(strpos($_SERVER['REQUEST_URI'], 'render/framed/file') !== FALSE) { $urlBlocks = ['VR', 'sizePixels', 'image', 'ver', 'frame', 'borderSize', 'mat', 'matSize', 'maxSize', 'frameGlass', 'minSize']; foreach($urlBlocks as $oneBlock) { if($pos = array_search($oneBlock, $urlParts)) { if(isset($urlParts[($pos+1)]) && $urlParts[($pos+1)] != '') { $_GET[$oneBlock] = $urlParts[$pos+1]; } } } // 后续图片生成、输出逻辑... }
注意:确保PHP代码前后没有多余的空白字符(比如<?php前的空格),否则会破坏缓存头和图片输出的完整性。
关键检查项
- 缓存目录权限:确保
/var/cache/nginx/fastcgi的所有者是Nginx运行用户(通常是www-data),执行chown -R www-data:www-data /var/cache/nginx/fastcgi修复权限。 - 缓存验证:用
curl -I https://你的域名/触发404的路径查看响应头,若出现X-Cache: HIT则说明缓存生效,MISS表示首次请求未命中缓存。
内容的提问来源于stack exchange,提问作者London Smith
相关产品推荐
相关产品推荐

