1

我使用 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;
  }

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

  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;
    }
  }
}
4

2 回答 2

2

有几件事需要调查:

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

使用 cookie 时强制缓存:

proxy_ignore_headers Cache-Control Expires Set-Cookie;

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

proxy_cache_methods GET HEAD POST PUT DELETE PATCH OPTIONS;

===

编辑:

试试这些设置:

在 /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 测试:

curl -X GET -I https://yoururl
于 2016-02-23T01:12:11.637 回答
-2

确保您指定了 proxy_cache_path (或者您的示例中没有包含它?)

于 2016-02-23T03:25:27.950 回答