JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Nginx完全指南--内容解析(五)

wys521 2024-09-17 02:24:49 精选教程 25 ℃ 0 评论

实现高性能负载均衡的进阶实操指南

经典书籍《NGINX 完全指南》中文版全新再版

这本由 O'Reilly 出版的电子书涵盖了最新的 NGINX 操作指南和使用技巧,是 NGINX 学习及实操的必备指南。新版不仅扩充更新了已有章节,还添加了不少前沿的热门话题。

本书是由中文官方网站推荐,免费下载的电子书籍,大家有兴趣的可以到官方地址下载获取,或者私信我获取。

中文官方网站:https://www.nginx-cn.net/

第4章 大规模可扩展的内容缓存


1、简介

缓存能够存储响应结果,以供未来再次使用,进而加速内容的提供。通过从缓存中提供内容,NGINX 可卸载上游(upstream)服务器的高开销、重复性工作,从而减少其负载。缓存可以提高性能并减少负载,这意味着您可以用更少的资源更快地提供服务。缓存还能减少提供资源所需的时间和带宽。

缓存服务器在战略位置上的扩展和分布会对用户体验产生巨大影响。最好将内容托管在靠近消费者的地方,这有助于释放最高性能。您还可以在靠近用户的地方缓存内容,内容交付网络(CDN)就采用了这种模式。NGINX 允许您在放置 NGINX 服务器的任何地方缓存内容,从而有效创建自己的 CDN。借助 NGINX 缓存,您还可以在上游(upstream)发生故障时被动地缓存并提供缓存的响应。缓存功能仅在 http 上下文中可用。本章将介绍 NGINX 的缓存和内容交付功能。

2、缓存区

想要缓存内容并定义缓存的存储位置。可使用 proxy_cache_path 指令定义共享内存缓存区和内容的位置:

proxy_cache_path /var/nginx/cache
 															keys_zone=main_content:60m
                             levels=1:2
                             inactive=3h
                             max_size=20g
                             min_free=500m;
proxy_cache CACHE;

上述缓存定义示例在文件系统 /var/nginx/cache 中为缓存响应创建了一个目录,以及一个名为 main_content、大小为 60M 的共享内存空间。此示例设置了目录结构级别,定义了如果缓存响应在 3 小时内未被请求就会被清除,同时定义了最大缓存大小为 20GB。

min_free 参数告知 NGINX 在清除缓存资源之前应在 max_size 的基础上保留多少磁盘空间。proxy_cache 指令通知特定上下文使用缓存区。proxy_cache_path 在 http 上下文中有效,proxy_cache 指令在 http、server 和 location 上下文中有效。

详解

要在 NGINX 中配置缓存,就必须声明要使用的路径和区域。您可以使用 proxy_cache_path 指令创建 NGINX 中的缓存区。proxy_cache_path 指令指定了存储缓存信息的位置,以及存储活动键和响应元数据的共享内存空间。该指令的可选参数对维护和访问缓存的方式提供了更多控制。

levels 参数定义了目录结构的创建方式。该值是一个以冒号分隔的数表,定义了连续子目录名称的长度。更深层次的结构有助于避免单个目录中出现过多缓存文件。它将结果存储在提供的文件结构中,使用缓存键作为文件路径并根据 levels 值分解目录。

intactive 参数能够控制缓存项在最后一次使用后驻留的时间长度。您也可以使用 max_size 参数配置缓存的大小。其他参数与缓存加载进程有关,这个进程可以将缓存键从磁盘的缓存文件及许多其他选项加载到共享内存区。

有关 proxy_cache_path 指令的更多信息,请访问下面“其他参考资料”部分中的文档链接。

其他参考资料

proxy_cache_path 文档:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_path

3、缓存哈希键

想要控制内容的缓存和检索方式,可使用 proxy_cache_key 指令和变量定义缓存的命中或未命中:

proxy_cache_key "$host$request_uri $cookie_user";

上述缓存哈希键将根据被请求的主机和 URI、定义用户的 cookie 指示 NGINX 缓存页面。这样您就可以缓存动态页面,而不用提供为其他用户生成的内容。

详解

proxy_cache_key 的默认配置是 "$scheme$proxy_host$request_uri",该配置适用于大多数用例。使用的变量包括 scheme(http 或 https)、proxy_host(发送请求)以及请求 URI。总之,这反映了 NGINX 将请求代理到哪个 URL。您可能会发现,还有许多其他因素定义了每个应用的唯一请求,比如请求参数、请求头、会话标识符等等,您希望为这些因素创建自己的哈希键。

暴露给 NGINX 的文本或变量的任何组合都可以用来形成一个缓存键。NGINX 提供了这些变量的列表。http://nginx.org/en/docs/varindex.html

选择一个好的哈希键非常重要,其中离不开对应用的了解。为静态内容选择缓存键通常非常简单,只需使用主机名和 URI 便可。但如果是为相当动态的内容(例如仪表盘应用的页面)选择缓存键,就要求对用户与应用的交互方式以及用户体验之间的差异程度有着更深刻的认识。缓存动态内容时,使用 cookie 或 JWT token 等会话标识符特别有用。出于安全考虑,您可能不希望在没有完全了解上下文的情况下就将用户的缓存数据展示给其他用户。proxy_cache_key 指令将字符串配置为缓存键的哈希值,该指令可以在 http、server 和 location 代码块中进行设置,从而灵活控制请求的缓存方式。

4、缓存锁定

希望控制 NGINX 如何处理对正在更新缓存的资源的并发请求,可使用 proxy_cache_lock 指令确保一次只能将一个请求写入缓存,随后的请求将等待响应被写入缓存并由此提供内容。

proxy_cache_lock on;
proxy_cache_lock_age 10s;
proxy_cache_lock_timeout 3s;

详解

我们不希望在代理请求时,之前对相同内容的请求仍在传输中,并且正在写入缓存。proxy_cache_lock 指令指示 NGINX 保存当前正在填充的最终将成为缓存资源的请求。根据 proxy_cache_lock_age 指令的定义,代理请求填充缓存的时间是有限制的,默认为 5 秒,此后才允许另一个请求填充资源。NGINX 还允许将已经等待指定时间 proxy_cache_lock_timeout(同样默认为 5 秒)的请求传递到代理服务器,该请求不会尝试来填充缓存。您可以将 proxy_cache_lock_age 理解成“你花的时间太长了,我来为你填充缓存”,将 proxy_cache_lock_timeout 理解成“你让我等的时间太长了,你先慢慢填充,我去干点别的”。

5、使用陈旧缓存

想要在上游(upstream)服务器不可用时发送过期缓存条目,可使用 proxy_cache_use_stale 指令和参数值来定义 NGINX 应使用陈旧缓存的场景。

proxy_cache_use_stale error timeout invalid_header updating
 http_500 http_502 http_503 http_504
 http_403 http_404 http_429;

详解

NGINX 能够在应用无法正确返回时提供陈旧缓存资源,这确实可以让问题迎刃而解。但这一功能会给最终用户造成 Web 服务正在运行的假象,而实际上后端可能已经无法访问。当出现问题时,从陈旧缓存提供内容还能减轻后端服务器的压力,从而让工程团队有些许时间调试解决问题。

当上游请求超时、返回 invalid_header 错误或返回 400 和 500 级响应码时,该配置会指示 NGINX 使用陈旧缓存资源。error 和 updating 参数有点特别。当无法选择上游服务器时,error 参数允许使用陈旧缓存。updating 参数会指示 NGINX 在缓存更新内容时使用陈旧缓存资源。

其他参考资料

NGINX 使用陈旧缓存指令文档 https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_use_stale

6、绕过缓存

有时您需要绕过缓存可使用具有非空或非零值的 proxy_cache_bypass 指令。动态执行此操作的一种方法是,在您不希望进行缓存的 location 代码块内,使用一组字符串不能为空或为 0 的变量:

proxy_cache_bypass $http_cache_bypass;

该配置指示 NGINX,如果名为 cache_bypass 的 HTTP 请求头的值不是 0,则绕过缓存。本例使用请求头作为变量来确定是否应该绕过缓存 —— 客户端需要专门为其请求设置此请求头。

详解

我们有很多使用场景都不要求缓存请求。为此,NGINX 提供了 proxy_cache_bypass 指令。这样,当值设置为非空或非零时,请求将被发送到上游(upstream)服务器,而不是从缓存中拉取。绕过缓存的不同需求和场景将由您的应用的用例来决定。绕过缓存可以简单到只需使用请求头或响应头就能搞定,也会复杂到协同配合多个 map 代码块来解决。

绕过缓存的原因有很多,比如为了故障排除或调试。如果您总是拉取缓存的页面,或者您的缓存键只是针对一个用户标识符的,那么复盘问题可能会很难。因此,具备绕过缓存的能力十分重要。绕过缓存的方法有很多,包括但不限于设置特定的 cookie、请求头或请求参数时等。您还可以通过设置 proxy_cache off;,彻底关闭给定上下文(例如location 代码块)的缓存功能。

7、NGINX Plus 之缓存清除

想要使缓存中的对象变得无效,可使用 proxy_cache_purge 指令(NGINX Plus 的清除功能)以及非空或零值变量。

map $request_method $purge_method {
     PURGE 1;
     default 0;
  }
    server {
       # ...
       location / {
           # ...
           proxy_cache_purge $purge_method;
       }
 }

在此示例中,如果使用 PURGE 方法请求特定对象,那么它的缓存将被清除。以下是使用curl 清除名为 main.js 的文件缓存的示例:

$ curl -X PURGE http://www.example.com/main.js

详解

处理静态文件的一种常见方法是将文件的哈希放在文件名中。当您推出新的代码和内容时,这可以确保您的 CDN 将其识别为新文件(因为 URI 已更改)。但是,对设置了不适合此模型的缓存键的动态内容来说,这种方法并不好用。在每种缓存场景中,您都必须有一种对应的清除缓存的方法。

NGINX Plus 的处理方法很简单,只要将 proxy_cache_purge 指令的值设置为零或非空,与请求匹配的缓存项就被会清除掉。此外还有一种简便方法,那就是为 PURGE 映射请求方法。但是您可能需要配合使用 geoip 模块或简单的身份验证方法,以确保不是任何人都能清除您宝贵的缓存项。NGINX 还允许使用 * 来清除与常见 URI 前缀相匹配的缓存项。要使用通配符,您需要使用 purger=on 参数配置 proxy_cache_path 指令。

其他参考资料

NGINX 缓存清除示例

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;
    }
}

8、缓存切片

想要通过将资源分段来提高缓存效率,可使用 NGINX slice 指令及其嵌入式变量将缓存结果分段:

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 就会中止这个段的缓存填充。如果内容确实发生了变化,文件也变小了,或者如果源端可以处理缓存填充过程中的负载峰值,那么最好使用实操指南 4.3 中所述的cache_lock 指令。请参阅“其他参考资料”部分中列出的博文,了解有关缓存切片技术的更多信息。

其他参考资料

“借助 NGINX 和 NGINX Plus 实现智能高效的字节范围缓存”

https://www.nginx-cn.net/blog/smart-efficient-byte-range-caching-nginx/


书末题署

《NGINX 完全指南》封面上的动物是欧亚猞猁(Lynx lynx),是最大的猞猁物种,分布范围广泛,从西欧延伸到中亚。猞猁的耳尖生有黑色耸立簇毛,两颊毛发浓密而粗糙。皮毛颜色从黄灰色到灰褐色,腹部为白色。这只猞猁通身布满黑斑,与南部地区的亚种相比,北部地区的亚种更灰白,斑点更少。

与其他猞猁物种不同,欧亚猞猁捕食较大的有蹄类动物,例如鹿、麋,甚至是驯养的绵羊。成年猞猁每天消耗两到五磅肉,可长达一周食用单一食物。欧亚猞猁在二十世纪中叶濒临灭绝,后来经过坚持不懈的保护,降级为无危物种。

O'Reilly 封面上的许多动物都濒临灭绝,但对世界意义重大。

封面插画由 Karen Montgomery 参考 Shaw 著作《Zoology(动物学)》中的黑白版画绘制而成。该系列由 Edie Freedman、Ellie Volckhausen 和 Karen Montgomery 共同设计。封面字体为微软雅黑系列字体,Neusa Next Std Bold 和 Arial 粗体。正文字体为微软雅黑和 Arial 字体,标题字体为微软雅黑粗体,Proxima Nova 粗体和 Arial 粗体,代码字体为 Dalton Maag's Ubuntu Mono。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表