(编辑:jimmy 日期: 2024/12/25 浏览:2)
我们都知道应用程序和网站的性能是他们成功的关键因素。但是,使您的应用程序或网站表现更好的过程并不总是很清楚。代码质量和基础架构当然至关重要,但在许多情况下,您可以通过专注于一些非常基本的应用程序的交付技术,对应用程序的最终用户体验进行大量改进。
其中一个例子是在应用程序栈中实现和优化缓存。在教程中介绍的技术可以帮助新手和高级用户使用 Nginx 中包含的内容缓存功能,从而获得更好的性能。
概览
内容缓存位于客户端和源服务器 (upstream) 之间,并保存它看到的所有内容的副本。如果客户端请求缓存已存储的内容,则它会直接返回内容而不连接源服务器。这提高了性能,因为内容缓存更靠近客户端,并且更有效地使用应用程序服务器,因为它们不必每次都从头开始生成页面。
Web 浏览器和应用程序服务器之间可能存在多个缓存:客户端的浏览器缓存,中间缓存,内容交付网络(CDN)以及位于应用程序服务器前面的负载平衡器或反向代理。即使在反向代理/负载均衡器级别,缓存也可以极大地提高性能。
这里举一个例子,比如我的站点使用 Next.js 服务器端口渲染,由于服务器性能比较差,当然 $5 的服务器,并不能期望好到那里去,能用就已经非常了不起,能进入这个局域网就好了,别期望太多。
每次打开页面将近花费 7 秒左右,当这其中包含网络延迟,但当我直接在服务器端(127.0.0.1) 发起请求时,时间接近 5 秒,然后再排除从数据库获取数据时间,服务器端渲染时间用了 4.5 秒,实在太慢,此时我能想到最快解决问题答案就是缓存,但在那里加入缓存,从每一步时间看来,在 Nginx 加入缓存最快解决问题
Nginx 通常作为应用程序堆栈中的反向代理或负载平衡器部署,并具有一整套缓存功能。下面我们将讨论如何使用 Nginx 配置基本缓存。
如何设置和配置基本缓存
只需要两个指令即可启用基本缓存:proxy_cache_path 和 proxy_cache。
proxy_cache_path 指令设置缓存的路径和配置,proxy_cache 用来指令激活它。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }
proxy_cache_path 指令的参数定义了以下设置:
缓存的本地磁盘目录称为 /path/to/cache/。
最后,该 proxy_cache 指令激活与父 location 块的 URL 匹配的所有内容的缓存(在示例中为/)。您还可以在 server 块中包含 proxy_cache 指令; 它适用于没有自己的 location 指令的服务器的所有块。
当上游服务器关闭()时提供缓存内容
Nginx 内容缓存的一个强大功能是,Nginx 可以配置为在无法从原始服务器获取新内容时从缓存中提供已缓存的内容。如果缓存资源的所有源服务器都已关闭或暂时占用,则会发生这种情况。
Nginx 不是将错误传递给客户端,而是从缓存中提供文件的陈旧版本。这为 Nginx 代理的服务器提供了额外的容错能力,并确保在服务器故障或流量高峰时的正常运行时间。要启用此功能,请包含 proxy_cache_use_stale 指令:
location / { # ... proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504; }
使用此示例配置,如果 Nginx 从原始服务器收到一个 error,timeout 或任何指定的 5xx 错误,并且在其缓存中具有所请求文件的过时版本,则它会传递过时文件,而不是将错误转发到客户端。
如何提高缓存性能
Nginx 具有丰富的可选设置,可用于微调缓存的性能。这是一个激活其中一些的例子:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on; proxy_pass http://my_upstream; } }
这些指令配置以下行为:
跨多个硬盘拆分缓存
如果您有多个硬盘驱动器,可以使用 Nginx 在它们之间拆分缓存。以下示例根据请求 URI 将客户端均匀分布在两个硬盘驱动器上:
proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off; proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g inactive=60m use_temp_path=off; split_clients $request_uri $my_cache { 50% “my_cache_hdd1”; 50% “my_cache_hdd2”; } server { # ... location / { proxy_cache $my_cache; proxy_pass http://my_upstream; } }
这两个 proxy_cache_path 指令在两个不同的硬盘驱动器上定义了两个缓存(my_cache_hdd1 和 my_cache_hdd2)。
split_clients 配置块指定从一半的请求(结果50%)被缓存在 my_cache_hdd1 与另一半中 my_cache_hdd2。基于 $request_uri 变量的哈希(请求URI)确定每个请求使用哪个缓存,结果是对给定URI的请求总是缓存在同一缓存中。
请注意,此方法不能替代 RAID 硬盘设置。如果存在硬盘驱动器故障,则可能导致系统出现不可预测的行为,包括用户看到针对故障硬盘驱动器的请求的 500 响应代码。适当的 RAID 硬盘设置可以处理硬盘故障。
如何对 Nginx Cache 进行检测
可以在响应头中加入 $upstream_cache_status 变量以进行检测
add_header X-Cache-Status $upstream_cache_status;
此示例 X-Cache-Status 在响应客户端时添加 HTTP 标头。以下是可能的值 $upstream_cache_status:
Nginx 如何确定是否要缓存响应
默认情况下,Nginx 尊重 Cache-Control 源服务器的标头。它不缓存响应 Cache-Control 设置为 Private,No-Cache 或 No-Store 或 Set-Cookie 在响应头。Nginx 只缓存 GET 和 HEAD 客户端请求。您可以按照以下答案中的说明覆盖这些默认值。
如果 proxy_buffering 设置为 off,Nginx 不会缓存响应。on 默认的。
Nginx 是否可以忽略 Cache-Control
使用 proxy_ignore_headers 指令可以忽略 Cache-Control
location /images/ { proxy_cache my_cache; proxy_ignore_headers Cache-Control; proxy_cache_valid any 30m; # ... }
Nginx 忽略 /images/ Cache-Control 下所有内容的标题。该指令强制缓存数据到期,如果忽略标头则需要。Nginx 不会缓存没有过期的文件。
Nginx 是否可以忽略 Set-Cookie
使用 proxy_ignore_headers 指令即可。
Nginx 如何缓存 POST 请求
使用 proxy_cache_methods 指令:
proxy_cache_methods GET HEAD POST;
此示例启用了POST请求的缓存。
Nginx 如何缓存动态内容
只要 Cache-Control 标头允许。即使在很短的时间内缓存动态内容也可以减少原始服务器和数据库的负载,从而缩短第一个字节的时间,因为不必为每个请求重新生成页面。
如何不使用 Nginx 缓存
proxy_cache_bypass 指令
location / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }
该指令定义了 Nginx 立即从源服务器请求内容的请求类型,而不是首先尝试在缓存中找到它。这有时被称为通过缓存 “打孔”。
Nginx 使用什么缓存密钥
Nginx 生成的密钥的默认形式类似于以下 Nginx 变量的 MD5 哈希:$scheme$proxy_host$request_uri; 使用的实际算法稍微复杂一些。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }
对于此示例配置,缓存密钥 http://www.example.org/my_image.jpg 计算为 md5(“http://my_upstream:80/my_image.jpg”)。
请注意,proxy_host 变量用于散列值而不是实际主机名(www.example.com)。proxy_host 定义为 proxy_pass 指令中指定的代理服务器的名称和端口。
要更改用作密钥基础的变量,请使用该 proxy_cache_key 指令。
使用 Cookie 作为我的缓存密钥的一部分
缓存键可以配置为任意值,例如:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;
此示例将 JSESSIONID cookie 的值合并到缓存键中。具有相同 URI 但 JSESSIONID 值不同的项目将作为唯一项目单独缓存。
Nginx 使用 ETag 标头
在 Nginx 1.7.3 及更高版本中,ETag 标头完全支持 If-None-Match。
Nginx 如何处理字节范围请求
如果文件在高速缓存中是最新的,则 Nginx 遵循字节范围请求并仅向项目客户端提供项目的指定字节。如果文件未缓存,或者文件过时,Nginx 会从原始服务器下载整个文件。
如果请求是针对单个字节范围的,则 Nginx 会在下载流中遇到该范围后立即将该范围发送到客户端。如果请求在同一文件中指定了多个字节范围,则 Nginx 会在下载完成时将整个文件传送到客户端。
下载完成后,Nginx 会将整个资源移动到缓存中,以便从缓存中立即满足所有未来的字节范围请求,无论是单个范围还是多个范围。
请注意,upstream 服务器必须支持 Nginx 的字节范围请求,以支持对该 upstream 服务器的字节范围请求。
Nginx 如何处理 Pragma 标头
在 Pragma:no-cache 报头由客户加入到绕过所有中间缓存,直接进入到源服务器的请求的内容。Pragma 默认情况下,Nginx 不支持标头,但您可以使用以下 proxy_cache_bypass 指令配置该功能:
location /images/ { proxy_cache my_cache; proxy_cache_bypass $http_pragma; # ... }
Nginx 是否支持标头 stale-while-revalidate 和 stale-if-error 以及扩展的 Cache-Control
Nginx 1.11.10 及更高版本中支持。这些扩展做了什么:
如果当前正在更新 stale-while-revalidate,Cache-Control HTTP 标头的扩展允许使用陈旧的缓存响应。HTTP 标头的 stale-if-error 扩展 Cache-Control 允许在发生错误时使用陈旧的缓存响应。这些头具有比较低优先级, proxy_cache_use_stale 指令如上所述。
Nginx 是否支持 Vary 标头
Nginx 1.7.7 以及更高版本中是支持 Vary 标头的 。
结论
至此,您应该很好地理解 Nginx 代理缓存的工作原理以及如何正确配置 Nginx 代理缓存。如果您有任何问题或反馈,请随时发表评论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。