我需要设置 NGINX,以便不同位置的缓存过期时间不同,并且某些位置的缓存会被禁用。这是我当前的设置:
fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=CACHE:200m inactive=100m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
...
set $no_cache 1;
...
if ($request_uri ~* "/some/cached/route") {
set $no_cache 0;
}
...
location ~ \.php$ {
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_cache CACHE;
fastcgi_cache_valid 200 30m;
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
...
}
通过此设置,我可以控制何时缓存响应,但无法控制缓存的有效时间。
我怎样才能使缓存有效时间变量?
答案1
原始回复
使用不同的缓存
fastcgi_cache_path /dev/shm/c1 levels=1:2 keys_zone=C1:50m inactive=1440m;
fastcgi_cache_path /dev/shm/c2 levels=1:2 keys_zone=C2:50m inactive=500m;
fastcgi_cache_path /dev/shm/c3 levels=1:2 keys_zone=C2:50m inactive=10m;
# absolute path
location = /path/to/resource {
fastcgi_cache C1; # etc
}
# regular expression
location ~* wp-admin {
fastcgi_cache C2; # etc
}
# catch-all
location ~ \.php$ {
fastcgi_cache C3; # etc
}
请注意,你必须了解顺序 Nginx 处理请求为了做到这一点,你可能必须使用正则表达式匹配 - 我发现这个正则表达式网站对于测试非常有用。不要使用“if”。如果是邪恶的。
更新。这个想法来自我的 Nginx 配置文件,它们在我的网站上运行。你可以在我的网站上下载我的配置。nginx 教程,第一部分。
更新 1
根据要求,这里有一个更完整的配置。这是从上面页面上的链接中截取的,因为它太长了。这只显示了主要的 PHP 块,而不是我做的其他事情,例如 wp-admin、静态图像热链接保护以及从 http 到 https 的转发等
# Caching. Putting the cache into /dev/shm keeps it in RAM, limited to 10MB, for one day.
# You can move to disk if you like, or extend the caching time
fastcgi_cache_path /dev/shm/hr_nginxcache levels=1:2 keys_zone=HR_CACHE:50m inactive=1440m; #RAM
upstream php {
server 127.0.0.1:9001;
}
# http production headphone reviews server
server {
server_name www.example.com;
listen 443 ssl http2;
ssl_certificate /var/lib/acme/certs/***CERT_DIRECTORY/fullchain;
ssl_certificate_key /var/lib/acme/certs/***CERT_DIRECTORY/privkey;
# Set up preferred protocols and ciphers. TLS1.2 is required for HTTP/2
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
root /var/www/***folder;
# First line is a cached access log, second logs immediately
access_log /var/log/nginx/hr.access.log main buffer=128k flush=60 if=$log_ua;
# Rules to work out when cache should/shouldn't be used
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments. 'admin' is for one of my websites, it's not required
# for everyone. I've removed index.php as I want pages cached.
#if ($request_uri ~* "/wp-admin/|/admin-*|/purge*|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
if ($request_uri ~* "/wp-admin/|/admin-*|/purge*|/xmlrpc.php|wp-.*.php|/feed/|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
# if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|code|PHPSESSID") {
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wordpress_logged_in|code") {
set $skip_cache 1;
}
# If we skip the cache it's likely customised for one user. Set the caching headers to match.
# http://www.mobify.com/blog/beginners-guide-to-http-cache-headers/
if ($skip_cache = 1) {
set $cacheControl "private, max-age=0, s-maxage=0, no-cache, no-store";
}
if ($skip_cache = 0) {
set $cacheControl "public, max-age=86400, s-maxage=86400";
}
# Default location to serve
location / {
# If the file can't be found try adding a slash on the end - it might be
# a directory the client is looking for. Then try the Wordpress blog URL
# this might send a few requests to PHP that don't need to go that way
try_files $uri $uri/ /blog/index.php?$args;
more_clear_headers Server; more_clear_headers "Pragma"; more_clear_headers "Expires";
# add_header Z_LOCATION "hr_root"; add_header URI $uri; # DEBUG
}
# Send HipHop and PHP requests to HHVM
location ~ \.(hh|php)$ {
fastcgi_keep_conn on;
fastcgi_intercept_errors on;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Use the cache defined above. Cache 200 (success) status's, for 24 hours, and cache
# specific other status's for an hour. This helps mitigate DDOS attacks.
# Only cache GET and HEAD requests
fastcgi_cache HR_CACHE;
fastcgi_cache_valid 200 1440m;
fastcgi_cache_valid 403 404 405 410 414 301 302 307 60m;
add_header X-Cache $upstream_cache_status;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Set the cache control headers we prepared earlier. Remove the old unnecessary Pragma and hide
# the server version. Clearing existing headers seems necessary
more_clear_headers "Cache-Control";
add_header Cache-Control $cacheControl;
more_clear_headers "Pragma"; more_clear_headers Server; more_clear_headers "Expires";
}
}
更新 2,将以上两部分放在一起
fastcgi_cache_path /dev/shm/c1 levels=1:2 keys_zone=C1:50m inactive=1440m;
fastcgi_cache_path /dev/shm/c2 levels=1:2 keys_zone=C2:50m inactive=500m;
fastcgi_cache_path /dev/shm/c3 levels=1:2 keys_zone=C2:50m inactive=10m;
# regular expression for directory app1
location ~* ^\/.*app1\/.*.php$ {
fastcgi_cache C1; # etc
}
# regular expression for directory app2
location ~ ^\/.*app2\/.*.php$ {
fastcgi_cache C2; # etc
}
# regular expression for directory app3
location ~ ^\/.*app3\/.*.php$ {
fastcgi_cache C3; # etc
}
答案2
最近我再次遇到了这个限制。
更清楚地重申问题:缓存多个不同的 PHP 响应,缓存时间长度不同。
我想出了这个办法:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /resource/.* {
try_files $uri $uri/ //index.php?$query_string;
}
location ~ /longresource/.* {
try_files $uri $uri/ ///index.php?$query_string;
}
location ~ //index\.php$ {
fastcgi_cache resources_cache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_methods GET;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~ ///index\.php$ {
fastcgi_cache resources_cache;
fastcgi_cache_valid 200 180m;
fastcgi_cache_methods GET;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
该代码片段来自 laravel 项目,其中所有内容都经过 index.php 文件。
这是有效的,因为//index.php
和/index.php
(以及具有任意数量的前置斜杠的相同位置)解析为同一个文件,但解析为不同的 nginx 位置块。
这是一个非常糟糕的黑客行为,经过了生产测试,并且没有干燥但它有效,你可以避免使用if
。