1、缓存区
缓存内容并定义缓存的存储位置。
使用 proxy_cache_path 指令定义共享内存缓存区和内容的位置:
bash
proxy_cache_path /var/nginx/cache
keys_zone=CACHE:60m
levels=1:2
inactive=3h
max_size=20g;
proxy_cache CACHE;
上述缓存定义示例在文件系统 /var/nginx/cache 中为缓存响应创建了一个目录,以及一个名为 CACHE、大小为 60M 的共享内存空间。此示例设置了目录结构级别,定义了如果缓存响应在 3 小时内未被请求就被释放,同时定义了最大缓存大小为 20GB。proxy_cache 指令通知特定上下文使用缓存区。proxy_cache_path 在 http 上下文中有效,proxy_cache 指令在 http、server 和 location 上下文中有效。
详解
要在 NGINX 中配置缓存,就必须声明要使用的路径和区域。您可以使用 proxy_cache_path 指令创建 NGINX 中的缓存区。proxy_cache_path 指定了存储缓存信息的位置,以及存储活动键和响应元数据的共享内存空间。该指令的可选参数对维护和访问缓存的方式提供了更多控制。levels 参数定义了文件结构的创建方式。该值用冒号分隔,声明了子目录名称的长度,最多支持三个级别。NGINX 缓存以缓存键(一个哈希值)为基础,它将结果存储在提供的文件结构中,使用缓存键作为文件路径并根据levels 值分解目录。inactive 参数能够控制缓存项在最后一次使用后驻留的时间长度。您也可以使用 max_size 参数配置缓存的大小。其他参数与缓存加载进程有关,这个进
程可以将缓存键从磁盘的缓存文件加载到共享内存
2、缓存锁定
您不希望 NGINX 将当前正在写入缓存的请求代理到上游(upstream)服务器。
使用 proxy_cache_lock 指令确保一次只能将一个请求写入缓存,随后的请求将等待响应被写入:
bash
proxy_cache_lock on;
proxy_cache_lock_age 10s;
proxy_cache_lock_timeout 3s;
详解
proxy_cache_lock 指令指示 NGINX 保存当前正在填充的请求,这些请求最终将成为被缓存的元素。根据 proxy_cache_lock_age 指令的定义,代理请求填充缓存的时间是有限制的,默认为 5 秒,此后才允许另一个请求填充元素。NGINX 还允许将已经等待指定时间(同样默认为 5 秒)的请求传递到代理服务器,该请求不会尝试通过使用 proxy_cache_lock_timeout 指令来填充缓存。您可以将 proxy_cache_lock_age 理解成"你花的时间太长了,我来为你填充缓存",将 proxy_cache_lock_timeout 理解成"你让我等的时间太长了,你先慢慢填充,我去干点别的"。
3、缓存哈希键
控制内容的缓存和检索方式。
使用 proxy_cache_key 指令和变量定义缓存的命中或未命中:
bash
proxy_cache_key "$host$request_uri $cookie_user";
上述缓存哈希键将根据被请求的主机和 URI、定义用户的 cookie 指示 NGINX 缓存页面。这样您就可以缓存动态页面,而且不用提供为其他用户生成的内容。
详解
proxy_cache_key 的默认配置是" s c h e m e scheme schemeproxy_host$request_uri",该配置适用于大多数用例。使用的变量包括 scheme、HTTP 或 HTTPS、proxy_host(发送请求)以及请求 URI。总之,这反映了 NGINX 将请求代理到哪个 URL。您可能会发现,还有许多其他因素定义了每个应用的唯一请求,比如请求参数、请求头、会话标识符等等,您希望为这些因素创建自己的哈希键。
选择一个好的哈希键非常重要,其中离不开对应用的了解。为静态内容选择缓存键通常非常简单,只需使用主机名和 URI 便可。但如果是为相当动态的内容(例如仪表盘应用的页面)选择缓存键,就要求对用户与应用的交互方式以及用户体验之间的差异程度有着更深刻的认识。出于安全考虑,您可能不希望在没有完全了解上下文的情况下就将用户的缓存数据展示给其他用户。proxy_cache_key 指令将字符串配置为缓存键的哈希值,该指令可以在 http、server 和 location 代码块中进行设置,从而灵活控制请求的缓存方式。
4、绕过缓存
绕过缓存。
使用具有非空或非零值的 proxy_cache_bypass 指令。动态执行此操作的一种方法是,在您不希望进行缓存的 location 代码块内,使用一组字符串不能为空或为 0 的变量:
bash
proxy_cache_bypass $http_cache_bypass;
该配置指示 NGINX,如果名为 cache_bypass 的 HTTP 请求头的值不是 0,则绕过缓存。本例使用请求头作为变量来确定是否应该绕过缓存 ------ 客户端需要专门为其请求设置此请求头。
详解
我们有很多使用场景都不要求缓存请求。为此,NGINX 提供了 proxy_cache_bypass 指令。这样,当值设置为非空或非零时,请求将被发送到上游(upstream)服务器,而不是从缓存中拉取。绕过缓存的不同需求和场景将由您的应用的用例来决定。绕过缓存可以简单到只需使用请求头或响应头就能搞定,也会复杂到协同配合多个 map 代码块来解决。
绕过缓存的原因有很多,比如为了故障排除或调试。如果您总是拉取缓存的页面,或者您的缓存键只是针对一个用户标识符的,那么复盘问题可能会很难。因此,具备绕过缓存的能力十分重要。绕过缓存的方法有很多,包括但不限于设置特定的 cookie、请求头或请求参数时等。您还可以通过设置 proxy_cache off;,彻底关闭给定上下文(例如 location 代码块)的缓存功能。
5、缓存性能
通过在客户端缓存内容来提高性能。
使用客户端的 cache-control HTTP 请求头:
bash
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public";
}
这个 location 代码块指定客户端可以缓存 CSS 和 JavaScript 文件的内容。expires 指令指示客户端将缓存资源的有效期设置为一年。add_header 指令将 HTTP 响应头Cache-Control 添加到响应中,值为 public,允许沿途的所有缓存服务器缓存资源。如果将值设置为 private,则只允许客户端缓存资源。
详解
缓存性能有许多影响因素,其中磁盘速度最为重要。NGINX 配置中有很多指令可以帮助提升缓存性能。其中一种方法是设置 HTTP 响应头,让客户端只缓存响应但是不向NGINX 发送请求,这样只需读取缓存便可。
6、NGINX Plus 之缓存清除
使缓存中的对象变得无效。
使用 proxy_cache_purge 指令(NGINX Plus 的清除功能)以及非空或零值变量:
bash
map $request_method $purge_method {
PURGE 1;
default 0;
}
server {
# ...
location / {
# ...
proxy_cache_purge $purge_method;
}
}
在此示例中,如果使用 PURGE 方法请求特定对象,那么它的缓存将被清除。以下是使用 curl 清除名为 main.js 的文件缓存的示例:
bash
$ curl -XPURGE localhost/main.js
详解
处理静态文件的一种常见方法是将文件的哈希放在文件名中。当您推出新的代码和内容时,这可以确保您的 CDN 将其识别为新文件(因为 URI 已更改)。但是,对设置了不适合此模型的缓存键的动态内容来说,这种方法并不好用。在每种缓存场景中,您都必须有一种对应的清除缓存的方法。NGINX Plus 的处理方法很简单,只要将 proxy_cache_purge 指令的值设置为非零或非空,与请求匹配的缓存项就被会清除掉。此外还有一种简便方法,那就是为 PURGE 映射请求方法。但是您可能需要配合使用 geo_ip 模块或简单的身份验证方法,以确保不是任何人都能清除您宝贵的缓存项。NGINX 还允许使用 * 来清除与常见 URI 前缀相匹配的缓存项。要使用通配符,您需要使用
purger=on 参数配置 proxy_cache_path 指令。
7、缓存切片
需要通过将文件分段来提高缓存效率。
使用 NGINX slice 指令及其嵌入式变量将缓存结果分段:
bash
proxy_cache_path /tmp/mycache keys_zone=mycache:10m;
server {
# ...
proxy_cache mycache;
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
proxy_cache_valid 200 206 1h;
location / {
proxy_pass http://origin:80;
}
}
详解
此配置为服务器定义并启用了一个缓存区。slice 指令指示 NGINX 将响应分成 1MB 的文件段。缓存文件根据 proxy_cache_key 指令进行存储。请注意,该指令使用了一个名为 slice_range 的嵌入式变量。向源端发送请求时也使用了同一变量作为请求头,并且该请求的 HTTP 版本已升级到 HTTP/1.1,因为 1.0 不支持字节范围的请求。200 或206 响应码的缓存有效期设为 1 个小时,然后定义位置和源端。
Cache Slice 模块是为了交付 HTML5 视频开发的,它使用字节范围的请求将伪流内容传输到浏览器。默认情况下,NGINX 能够从缓存中提供字节范围的请求。如果对未缓存的内容发出了一个字节范围的请求,NGINX 将向源端请求整个文件。当您使用Cache Slice 模块时,NGINX 仅向源端请求必要的文件段。如果请求范围大于切片大小(包括整个文件),就会触发对每个所需文件段的子请求,并对这些文件段进行缓存处理。当所有文件段都被缓存后,系统将组合响应并将它们发送给客户端,这使得NGINX 能够更有效地缓存并提供请求的范围内的内容。
Cache Slice 模块只能用于不会进行更改的大文件。NGINX 每接收一个来自源端的文件段,就验证一次 ETag。如果源端的 ETag 发生了变化,那么由于缓存不再有效,NGINX 就会中止这个段的缓存填充。如果内容确实发生了变化,文件也变小了,或者如果源端可以处理缓存填充过程中的负载峰值,那么最好使用下面"其他参考资料"所列博客中描述的 Cache Lock 模块。默认情况下不创建该模块,您需要在构建 NGINX 时使用 --with-http_slice_module 配置来启用。