Назад | Перейти на главную страницу

nginx fastcgi caching - несколько разных сроков истечения

Мне нужно настроить 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;
    }
    ...
}

С помощью этой настройки я могу контролировать, когда ответ должен быть кэширован, но не могу контролировать, как долго кеш будет действителен.

Как я могу сделать кеш действительной переменной времени?

Оригинальный ответ

Используйте разные кеши

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 обрабатывает запросы чтобы понять это правильно, и вам, вероятно, придется использовать сопоставление регулярных выражений - я считаю этот сайт с регулярным выражением очень полезно для тестирования. Не используйте «если». Если это зло.

Обновить. Эта идея исходит из моих файлов конфигурации 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
}

Недавно я снова столкнулся с этим ограничением.

Чтобы повторить проблему более четко: кешируйте несколько разных ответов 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.