假设我们有一个 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
|