7.内容缓存
缓存来自代理 Web 和应用程序服务器的静态和动态内容,以加快向客户端的交付速度并减少服务器上的负载。 启用缓存后,NGINX将响应保存在磁盘缓存中,并使用它们来响应客户端,而不必每次都代理对相同内容的请求。
启用响应缓存
若要启用缓存,请在顶级 http {}上下文中包含 proxy_cache_path 指令。必需的第一个参数是缓存内容的本地文件系统路径,必需参数 keys_zone定义用于存储有关缓存项的元数据的共享内存区域的名称和大小:
http {
# ...
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m;
}
然后在要缓存服务器响应的上下文(协议类型、虚拟服务器或location)中包含 proxy_cache 指令,并指定由 proxy_cache_path指令 keys_zone参数定义的区域名称(在本例中为 mycache ):
http {
# ...
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m;
server {
proxy_cache mycache;
location / {
proxy_pass http://localhost:8000;
}
}
}
请注意,keys_zone参数定义的大小不会限制缓存响应数据的总量。缓存的响应本身与元数据的副本一起存储在文件系统上的特定文件中。要限制缓存的响应数据量,请将 max_size参数包含在 proxy_cache_path 指令中。(但请注意,缓存的数据量可能会暂时超过此限制,如下一节所述。
缓存中涉及的 NGINX 进程
缓存中还涉及两个额外的 NGINX 进程:
- 缓存管理器(cache manager) 会定期激活以检查缓存的状态。如果高速缓存大小超过
proxy_cache_path指令max_size参数设置的限制,高速缓存管理器将删除最近最少访问的数据。如前所述,缓存的数据量可能会在缓存管理器激活之间的时间内暂时超过限制。 - 缓存加载程序(cache loader) 仅在NGINX启动后运行一次。它将有关以前缓存数据的元数据加载到共享内存区域中。一次加载整个缓存可能会消耗足够的资源,从而在启动后的最初几分钟内降低NGINX性能。若要避免这种情况,请通过将以下参数包含在
proxy_cache_path指令中来配置缓存的迭代加载: loader_threshold– 迭代的持续时间,以毫秒为单位(默认情况下,200)loader_files– 一次迭代期间加载的最大项目数(默认情况下,100)loader_sleeps– 迭代之间的延迟,以毫秒为单位(默认情况下,50)
在以下示例中,迭代持续至少 300毫秒直到 200加载项加载完成:
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m loader_threshold=300 loader_files=200;
指定要缓存的请求(Specifying Which Requests to Cache)
默认情况下,NGINX会在第一次从代理服务器收到此类响应时缓存对使用HTTP GET和 HEAD方法发出的请求的所有响应。作为请求的密钥(标识符)。如果请求与缓存的响应具有相同的键,NGINX Plus会将缓存的响应发送到客户端。您可以在 http {},server {} 或 location {}上下文中包含各种指令,以控制缓存哪些响应。
要更改用于计算密钥的请求特征,请包含 proxy_cache_key 指令:
proxy_cache_key "$host$request_uri$cookie_user";
要定义在缓存响应之前必须发出具有相同键的请求的最小次数,请包括 proxy_cache_min_uses 指令:
proxy_cache_min_uses 5;
要使用 GET 和 HEAD 以外的方法缓存对请求的响应,请将它们与 GET 和 HEAD 一起列为 <span> </span>proxy_cache_methods 指令的参数:
proxy_cache_methods GET HEAD POST;
限制或禁用缓存
默认情况下,响应无限期地保留在缓存中。仅当缓存超过最大配置大小时,才会删除它们,然后按自上次请求它们以来的时间长度排序。您 可以通过在 http {},server {}或 location {}上下文中包含指令来设置缓存响应被视为有效的时间,甚至是否使用它们:
要限制具有特定状态代码的缓存响应被视为有效的时间,请包含 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;
要定义NGINX不向客户端发送缓存响应的条件,请包括 proxy_cache_bypass指令。每个参数定义一个条件,并由许多变量组成。如果至少有一个参数不为空且不等于“0”(零),NGINX 不会在缓存中查找响应,而是立即将请求转发到后端服务器。
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
从缓存中清除内容
NGINX可以从缓存中删除过时的缓存文件。这对于删除过时的缓存内容以防止同时提供旧版和新版本的网页是必需的。缓存在收到包含自定义 HTTP 标头或 HTTP PURGE方法的特殊“清除”请求时被清除。
配置缓存清除
让我们设置一个配置来标识使用 HTTP PURGE 方法的请求并删除匹配的 URL。
在 http {}上下文中,创建一个新变量,例如,$purge_method依赖于该 $request_method变量:
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;
}
}
发送清除命令
配置 proxy_cache_purge指令后,需要发送特殊的缓存清除请求来清除缓存。您可以使用一系列工具发出清除请求,包括以下示例中的 curl命令:
$ curl -X PURGE -D – "https://www.example.com/*"
HTTP/1.1 204 No Content
Server: nginx/1.15.0
Date: Sat, 19 May 2018 16:33:04 GMT
Connection: keep-alive
在此示例中,将清除具有公共 URL 部分(由星号通配符指定)的资源。但是,此类缓存条目不会从缓存中完全删除:它们将保留在磁盘上,直到它们因不活动(由 proxy_cache_path 指令的 inactive参数确定)或缓存清除器(使用 purger 参数启用 proxy_cache_path)而被删除,或者客户端尝试访问它们。
限制对清除命令的访问
建议限制允许发送缓存清除请求的 IP 地址数:
geo $purge_allowed {
default 0; # deny from other
10.0.0.1 1; # allow from 10.0.0.1 address
192.168.0.0/24 1; # allow from 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拒绝清除。
从缓存中完全删除文件
要完全删除与星号匹配的缓存文件,请激活一个特殊 cache purger进程,该进程将永久循环访问所有缓存条目并删除与通配符键匹配的条目。在 http {}上下文中包含 purger 参数到 proxy_cache_path指令:
缓存清除配置示例
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;
}
}
字节范围缓存
初始缓存填充操作有时需要相当长的时间,尤其是对于大文件。例如,当视频文件开始下载以满足对文件一部分的初始请求时,后续请求必须等待整个文件下载并放入缓存中。
NGINX可以缓存此类范围请求,并使用缓存切片模块逐渐填充缓存,该模块将文件划分为较小的“切片(Cache Slice)”。每个范围请求都会选择覆盖所请求范围的特定切片,如果此范围仍未缓存,则将 其放入缓存中。对这些切片的所有其他请求都会从缓存中获取数据。
要启用字节范围缓存,请执行以下操作:
-
确保NGINX是使用缓存切片模块编译的。
-
使用 slice 指令指定切片的大小:
location / {
slice 1m;
}选择可加快切片下载速度的切片大小。如果大小太小,则内存使用量可能过多,并且在处理请求时打开了大量文件描述符,而过大可能会导致延迟。
-
将
$slice_range变量包含在缓存键中:proxy_cache_key $uri$is_args$args$slice_range; -
使用
206状态代码启用响应缓存:proxy_cache_valid 200 206 1h; -
通过在
Range标头字段中设置$slice_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;
}
请注意,如果切片缓存处于打开状态,则不得更改初始文件。
组合配置示例
以下示例配置结合了上述一些缓存选项。
http {
# ...
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m loader_threshold=300
loader_files=200 max_size=200m;
server {
listen 8080;
proxy_cache mycache;
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;
}
}
}
在此示例中,两个位置使用相同的缓存,但方式不同。
由于 backend1响应很少更改,因此不包括缓存控制指令。响应在首次发出请求时缓存,并无限期有效。
相比之下,对 backend2请求的响应经常更改,因此它们被认为仅在 1 分钟内有效,并且在发出 3 次相同的请求之前不会 缓存。此外,如果请求符合 proxy_cache_bypass指令定义的条件,NGINX会立即将请求传递给 backend2,而无需在缓存中查找相应的响应。