如何在 NGINX 中缓存一个特定的反向代理路由



我正在使用nginx作为反向代理,这是我配置中的一个片段,它将/api调用下的任何内容路由到内部API服务器:

  # API server
  location /api {
    if ($request_method = OPTIONS) {
      return 204;
    }
    # Proxy settings
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://my.api-server.com
    # Error handlers
    error_page 504 /errors/504.json;
    # CORS headers
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Allow' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Referrer, User-Agent, Authorization, X-Impersonate-As, X-Request-Context' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Expose-Headers' 'Authorization, X-Request-Id, X-Server-Time' always;
    add_header 'Access-Control-Max-Age' 3628800;
  }

但是现在我想允许一个规则缓存一个特定的反向代理路由(比如 TTL = 30 分钟的 /api/foo/bar),我尝试了这个:

  location /api {
    if ($request_method = OPTIONS) {
      return 204;
    }
    if ($request_uri ~* /api/foo/bar) {
      proxy_cache_valid 200 301 302 30m;
      add_header X-Cache $upstream_cache_status;
    }
    ....

但是,这是行不通的。最好的方法是什么?

编辑:

完整服务器配置:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
  worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    gzip  on;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_vary on;
    gzip_types text/plain
               text/xml
               text/css
               text/javascript
               application/json
               application/javascript
               application/x-javascript
               application/ecmascript
               application/xml
               application/rss+xml
               application/atom+xml
               application/rdf+xml
               application/xml+rss
               application/xhtml+xml
               application/x-font-ttf
               application/x-font-opentype
               application/vnd.ms-fontobject
               image/svg+xml
               image/x-icon
               application/atom_xml;
    gzip_buffers 16 8k;
    add_header X-Frame-Options SAMEORIGIN;
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    keepalive_timeout           60;
    proxy_connect_timeout       60;
    proxy_send_timeout          60;
    proxy_read_timeout          60;
    send_timeout                60;
    client_max_body_size 100M;
    proxy_cache_path /dev/shm levels=1:2 keys_zone=mcache:16m inactive=600s max_size=512m;
    proxy_cache_methods GET HEAD;
    proxy_cache_min_uses 1;
    proxy_cache_key "$request_method$host$request_uri";
    proxy_cache_use_stale timeout updating;
    proxy_ignore_headers Cache-Control Expires Set-Cookie;
    server {
      listen 80;
      server_name my.company.com;
      return 301 https://$host$request_uri;
    }
  server {
    listen 443 http2 default_server ssl;
    server_name my.company.com;
    ssl_certificate     /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/cert.key;
    ssl on;
    # API server
    location /api {
      if ($request_method = OPTIONS) {
        return 204;
      }
      # Proxy settings
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://internal-api-server;
      # Error handlers
      error_page 504 /errors/504.json;
    if ($request_uri ~* /api/foo/bar) {
      proxy_cache_bypass 0;
      proxy_no_cache     0;
      proxy_cache        mcache; # mcache=RAM
      proxy_cache_valid 200 301 302  30m;
      proxy_cache_valid 403 404      5m;
      proxy_cache_lock   on;
      proxy_cache_use_stale timeout updating;
      add_header X-Proxy-Cache $upstream_cache_status;
    }
      # CORS headers
      add_header 'Access-Control-Allow-Origin' '*' always;
      add_header 'Allow' '*' always;
      add_header 'Access-Control-Allow-Methods' 'GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS' always;
      add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Referrer, User-Agent, Authorization, X-Impersonate-As, X-Request-Context' always;
      add_header 'Access-Control-Allow-Credentials' 'true' always;
      add_header 'Access-Control-Expose-Headers' 'Authorization, X-Info-Resources' always;
      add_header 'Access-Control-Max-Age' 3628800 always;
    }
    location ^~ /errors/ {
      internal;
      root /etc/nginx/static-files/;
    }
    location /nginx_status {
      stub_status on;
      access_log off;
    }
  }
}

有几件事需要研究:

  1. 默认情况下,Nginx 只缓存 GET 和 HEAD 请求。
  2. 默认情况下,Nginx不会缓存任何POST或任何带有COOKIE的内容。

要在使用 Cookie 时强制缓存,请执行以下操作:

proxy_ignore_headers Cache-Control Expires Set-Cookie;

要使用其他请求方法进行缓存(选择您自己的方法):

proxy_cache_methods GET HEAD POST PUT DELETE PATCH OPTIONS;

===

编辑:

请尝试以下设置:

On/etc/nginx

/nginx.conf

proxy_cache_path /dev/shm levels=1:2 keys_zone=mcache:16m inactive=600s max_size=512m;
proxy_cache_methods GET HEAD;
proxy_cache_min_uses 1;
proxy_cache_key "$request_method$host$request_uri";
proxy_cache_use_stale timeout updating;
proxy_ignore_headers Cache-Control Expires Set-Cookie;

在您的位置块上:

location /api/foo/bar {
    proxy_cache_bypass 0;
    proxy_no_cache     0;
    proxy_cache        mcache; # mcache=RAM
    proxy_cache_valid 200 301 302  30m;
    proxy_cache_valid 403 404      5m;
    proxy_cache_lock   on;
    proxy_cache_use_stale timeout updating;
    add_header X-Proxy-Cache $upstream_cache_status;
}

确保 Nginx 已重新加载(或停止 + 启动)

service nginx reload

用卷曲测试:

curl -X GET -I https://yoururl

确保指定proxy_cache_path(或者只是不包含在您的示例中?

相关内容

最新更新