第九节——NGINX内容缓存

  • 来源:新网
  • 更新日期:2018-04-18

摘要:缓存启用时,NGINX保存响应到磁盘缓存,客户端每次请求相同内容时无需代理请求,直接使用缓存内容响应客户端。

1 概述

缓存启用时,NGINX保存响应到磁盘缓存,客户端每次请求相同内容时无需代理请求,直接使用缓存内容响应客户端。

2 启用响应缓存

为了启用缓存,在http上下文中设置proxy_cache_path指令。第一个必选参数是缓存内容的本地文件系统路径,必选参数keys_zone定义用于存储缓存条目的元数据的共享内存区域的名称和大小:

http { # ... proxy_cache_path /data/nginx/cache keys_zone=one:10m; }

然后在你想要缓存服务器响应的上下文(协议类型、虚拟主机或location)中使用proxy_cache指令,指定proxy_cache_path指令的keys_zone参数定义的区域名称(在这种情况下,是one):

http { # ... proxy_cache_path /data/nginx/cache keys_zone=one:10m; server { proxy_cache one; location / { proxy_pass http://localhost:8000; } } }

注意,keys_zone参数定义的大小不限制缓存响应数据的总大小。缓存的响应本身存储在文件系统中特定文件的元数据副本中。使用proxy_cache_path指令的max_size参数限制缓存响应数据的总大小。(但是注意,缓存数据的总大小可以临时超过这个限制。)

t015dbf740341063496.jpg

3 涉及缓存的NGINX进程

有两个额外NGINX进程涉及缓存:

缓存管理器定期被激活检查缓存的状态。如果缓存大小超过proxy_cache_path指令的max_size参数设置的限制,缓存管理器删除最近访问的数据。如前所述,大多数缓存数据能在缓存管理器激活期间临时超过限制。 缓存加载器只在NGINX启动后运行一次。它加载之前缓存数据到共享内存区域的元数据。在第一次启动后几分钟加载整个缓存立即消耗大量资源,导致NGINX性能降低。为了避免这个问题,在proxy_cache_path指令上配置迭代加载缓存的参数: loader_threshold:迭代周期,以毫秒为单位(默认是200)。 loader_files:一次加载的最大项目数(默认是100)。 loader_sleeps:两次迭代之间的延迟,以毫秒为单位(默认是50)。

在下面例子中,每次迭代加载至少300毫秒或至少加载200个项目:

proxy_cache_path /data/nginx/cache keys_zone=one:10m loader_threshold=300 loader_files=200; 4 指定哪些请求被缓存

默认,NGINX缓存所有第一次使用HTTP GET和HEAD方法的请求的响应,响应接收自代理服务器。NGINX使用请求字符串作为请求的缓存键。如果请求与缓存的响应有相同的缓存键,NGINX发送缓存响应到客户端。可以在httpserverlocation上下文中包括各种指令控制那些响应被缓存。

使用proxy_cache_key指令修改缓存键的计算方式:

proxy_cache_key "$host$request_uri$cookie_user";

使用proxy_cache_min_uses指令定义请求使用相同缓存键至少多少次后响应才被缓存:

proxy_cache_min_uses 5;

使用proxy_cache_methods指令缓存GET和HEAD之外的请求的响应:

proxy_cache_methods GET HEAD POST; 5 限制或禁用缓存

默认,响应无限期的保存在响应中。只有当超过配置的最大大小时,才会按最后请求的时间远近顺序删除。可以设置缓存响应多久失效,甚至是否它们一直使用。

使用proxy_cache_valid指令限制特定状态码响应的有效时间:

proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m;

在上面例子中,状态码为200或302的响应有效期是10分钟,状态码为404的响应有效期是1分钟。为了定义所有响应的有效期使用any作为第一个参数:

proxy_cache_valid any 5m;

使用proxy_cache_bypass指令定义NGINX不发送缓存响应到客户端的条件。每个参数定义一个条件,由大量变量组成。如果至少一个参数不为空并且不等于“0”,NGINX就不在缓存中查找响应,而是立即将请求转发到后端服务器。

proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;

使用proxy_no_cache指令定义NGINX不缓存响应的条件。与proxy_cache_bypass参数相同。

proxy_no_cache $http_pragma $http_authorization; 6 清理缓存内容

NGINX可以清理过期缓存文件。为了防止同时服务新老版本的Web页面,非常有必要清理过期缓存内容。当接收到特定包含自定义HTTP头或HTTP PURGE方法的“purge”请求时,NGINX清理过期的缓存。

6.1 配置缓存清理

下面例子配置,使用PURGE HTTP方法标识请求并删除匹配的URI。

http上下文中,使用map指令创建一个变量,例如:

http { # ... map $request_method $purge_method { PURGE 1; default 0; } } 在location块中配置了缓存,使用proxy_cache_purge指令指定清理缓存请求的条件。在我们的例子中,使用上一步配置的$purge_method

server { listen 80; server_name www.example.com; location / { proxy_pass https://localhost:8002; proxy_cache mycache; proxy_cache_purge $purge_method; } } 6.2 发送清理命令

proxy_cache_purge指令被配置时,可以发送一条特定的缓存清理请求清理缓存。有一系列的发送请求工具,例如,curl命令:

$ curl -X PURGE -D – "https://www.example.com/*" HTTP/1.1 204 No Content Server: nginx/1.5.7 Date: Sat, 01 Dec 2015 16:33:04 GMT Connection: keep-alive

在例子中,有一个公共URL部分(通过星号通配符指定)的资源备清理。然而,这些缓存条目不会完全从缓存中删除:它们会保留在磁盘上,直到它们不活跃(通过proxy_cache_path指令的inactive参数决定)或清理缓存(使用proxy_cache_path指令的purger参数启用),或客户端尝试访问它们时删除。

6.3 限制清理命令访问

推荐限制允许发送清理缓存请求的IP地址的数量:

geo $purge_allowed { default 0; # 拒绝其他IP地址 10.0.0.1 1; # 允许从10.0.0.1访问 192.168.0.0/24 1; # 允许从192.168.0.0/24访问 } map $request_method $purge_method { PURGE $purge_allowed; default 0; }

在该例子中,NGINX检查该请求是否是“PURGE”方法,如果是,分析客户端的IP地址。如果IP地址是白名单,那么$purge_method设置$purge_allowed为:1,允许清理,0,拒绝清理。

6.4 完全删除缓存文件

为了完全删除匹配星号的缓存文件,激活特定缓存清理进程,永久编译所有缓存条目并删除匹配通配符的条目。包括purger参数到http上下文的proxy_cache_path指令:

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on; 6.5 清理缓存配置示例

http { # ... proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on; map $request_method $purge_method { PURGE 1; default 0; } server { listen 80; server_name www.example.com; location / { proxy_pass https://localhost:8002; proxy_cache mycache; proxy_cache_purge $purge_method; } } geo $purge_allowed { default 0; 10.0.0.1 1; 192.168.0.0/24 1; } map $request_method $purge_method { PURGE $purge_allowed; default 0; } } 7 字节范围缓存

最初的缓存填充操作有时可能需要一些时间,尤其对于大文件。例如,当一个视频文件开始下载到完成文件一部分的初始请求,后续请求必须等待整个文件被下载并放入缓存。

NGINX可以缓存范围请求,使用Cache Slice模块逐步填充缓存,切分文件到更小的“片段”。每个范围请求选择特定片段,如果该范围没有缓存,放入缓存中。这些片段的其它请求直接从缓存获取数据。

为了启用字节范围缓存:

确认NGINX编译了Cache Slice模块。 使用slice指令指定分片大小。

location / { slice 1m; }

选择一个能足够快下载分片的分片大小。太小可能导致浪费过多的内存,并且处理请求时要打开大量的文件描述符,而值太大会导致延迟。

包括$slice_range变量到缓存键中

proxy_cache_key $uri$is_args$args$slice_range; 启用状态码为206的响应的缓存:

proxy_cache_valid 200 206 1h; 启用传入范围请求到代理服务器通过传入$slice_range变量到Range头字段:

proxy_set_header Range $slice_range;

二进制范围缓存例子:

location / { slice 1m; proxy_cache cache; proxy_cache_key $uri$is_args$args$slice_range; proxy_set_header Range $slice_range; proxy_cache_valid 200 206 1h; proxy_pass http://localhost:8000; }

注意,如果分片缓存打开,最初的文件不会改变。

7.1 联合示例配置

http { # ... proxy_cache_path /data/nginx/cache keys_zone=one:10m loader_threshold=300 loader_files=200 max_size=200m; server { listen 8080; proxy_cache one; location / { proxy_pass http://backend1; } location /some/path { proxy_pass http://backend2; proxy_cache_valid any 1m; proxy_cache_min_uses 3; proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment; } } }

在该例子中,两个location使用相同的缓存,但方式不同。

因为来自backend1服务器的响应很少改变,没有缓存控制指令。第一次响应缓存的请求,并永久保存。

相比之下,来自backend1服务器的响应改变频繁,因此它们的有效期只有1分钟并且直到同样的请求发生三次才会缓存。然而,如果proxy_cache_bypass指令指定请求匹配条件,NGINX立即传递请求给backend2而不去检查缓存。