nginx fastcgi 缓存-多个不同的过期时间

nginx fastcgi 缓存-多个不同的过期时间

我需要设置 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

相关内容