使用NGINX+ mirror实现API缓存更新


假设我们有一个 URI /profile/syshero。

  • 如果向 /profile/syshero 发送 GET,应用程序就会向客户端提供输出结果。
  • 如果向 /profile/syshero 发送 PUT/POST/DELETE,应用程序将执行写操作并更改内容

这一概念与 REST API 的工作原理类似,因此这种方法与大量 REST 应用程序兼容。

理想的解决方案是:

  • 为 GET/HEAD 请求缓存或提供缓存内容
  • 如果是任何其他 HTTP 方法(如 POST、PUT、DELE)的缓存内容:POST、PUT、DELETE、PATCH、MKCOL 等则清除缓存内容

下面的配置通过使用 NGINX+ 镜像模块和purge选项实现了这一点。


proxy_cache_path /tmp/nginx levels=1:2 keys_zone=default:10m max_size=50m;

upstream backends {
  zone backends 32k;
  server service.consul service=backend resolve;
}

server {
  status_zone default;

  listen 80;
  server_name _;

  root /usr/share/nginx/html;

  add_header X-Cache-Status $upstream_cache_status;

  location / {
    mirror /mirror;
    mirror_request_body off;
    proxy_cache_valid 200 1m;
    proxy_cache default;
    proxy_cache_key $uri;
    proxy_pass http://backends;
  }

  location /mirror {
    internal;
    if ($request_method ~
"HEAD|GET") {
      return 204;
    }
    proxy_pass_request_body off;
    proxy_set_header Content-Length
"";
    proxy_cache_purge 1;
    proxy_cache default;
    proxy_cache_key $request_uri;
    proxy_pass http:
//backends$request_uri;
  }
}

该配置接收任何指向 / 的请求,将其转发给后端服务器,并将该请求镜像到 /mirror 位置。

  • 对于 GET 和 HEAD 方法,位置 /mirror 将返回 204,因为我们希望避免重复向后端发送所有请求,同时也避免在每次请求时都清除缓存
  • 而对于其他非 GET 或 HEAD 方法,则会清除特定 URI 的缓存。

需要注意的一点是,正如你所看到的,两个位置块中的 proxy_cache_key 都需要不同的key值,这是为什么呢?这是因为镜像模块的工作方式。为了在两个区块中使用相同的值,必须使用 $uri 和 $request_uri。

下面是测试:

root@host:~# curl -v http://localhost/data 2>&1 | grep X-Cache-Status
< X-Cache-Status: HIT
root@host:~# curl -X POST --data
"test=1" -v http://localhost/data 2>&1 | grep X-Cache-Status
root@host:~# curl -v http:
//localhost/data 2>&1 | grep X-Cache-Status
< X-Cache-Status: MISS
root@host:~# curl -v http:
//localhost/data 2>&1 | grep X-Cache-Status
< X-Cache-Status: HIT