📢 Nginx 缓存是什么
Nginx 缓存是一种提高 Web 服务器性能的方法,通过存储先前请求的内容的副本,从而减少对源服务器的重复请求。
🔍 作用
- 减少响应时间:通过提供缓存的内容,可以更快地响应客户端的请求。
- 减少源服务器的负载:减少对源服务器的请求次数,从而减少资源使用并提高整体性能。
- 带宽节省:减少重复的内容传输,从而节省带宽。
- 提高内容可用性:即使源服务器暂时不可用或超载,缓存的内容仍可供访问。
🏞️ 使用场景
- 高流量网站:对于访问量巨大的网站,缓存可以大大提高响应速度并减少源服务器的负载。
- 内容分发网络 (CDN):Nginx 可作为 CDN 的边缘节点,为全球用户提供缓存的内容。
- 反向代理:在复杂的后端系统前放置 Nginx,利用其缓存功能提高性能。
- API 网关:缓存常用的 API 响应,减少数据库或后端服务的查询。
✅ 优点
- 性能提升:缓存减少了对源服务器的请求,从而加速响应时间。
- 可靠性增强:即使源服务器出现问题,缓存内容仍可供用户访问。
- 带宽节省:减少相同内容的重复传输。
- 灵活性:Nginx 提供了丰富的缓存配置选项,可以根据需要进行微调。
❌ 缺点
- 数据一致性:缓存内容可能与源内容不同步,特别是在高变化的内容中。
- 管理复杂性:需要定期维护和更新缓存,以及配置适当的过期策略。
- 资源使用:虽然减少了对源服务器的负载,但缓存本身需要存储空间和管理。
- 可能的缓存雪崩:当大量缓存同时到期时,可能导致对源服务器的大量请求。
🌐 Nginx 内容缓存
Nginx 的 proxy_cache
利用数据的局部性原理来存储先前被访问的资源,从而使得这些资源可以被直接从前端服务器获取,而不是每次都从后端服务器请求。这不仅可以减少后端服务器的负担,还可以减少整体的响应时间。
📁 缓存路径配置
当你配置 Nginx 以使用代理缓存时,第一步是定义缓存的存储位置和相关的参数。这是通过📁 proxy_cache_path
指令完成的。让我们深入了解这个指令及其参数:
http {
...
# 定义缓存的存储路径
proxy_cache_path /usr/local/nginx/cache
# 使用二级目录结构
levels=1:2
# 共享内存区域名称为 "the_cache_zone",大小为10MB
keys_zone=the_cache_zone:10m
# 1小时内未被访问的数据会被删除
inactive=1h
# 缓存最大可使用512MB的磁盘空间
max_size=512m
# 响应直接写入缓存路径
use_temp_path=off;
...
}
1️⃣ 路径:
/usr/local/nginx/cache
: 这是缓存内容存储的文件系统路径。Nginx 将在这里创建缓存文件。
2️⃣ levels:
levels=1:2
: 定义缓存目录的层级结构。在这种情况下,我们使用二级目录结构,这有助于防止文件系统目录中有太多的条目,这可能会导致性能问题。
3️⃣ keys_zone:
keys_zone=the_cache_zone:10m
: 这定义了一个共享内存区域的名称和大小,用于存储缓存键和元数据。the_cache_zone
: 这是共享内存区域的名称。10m
: 分配给这个区域的内存大小。这里是10MB。
4️⃣ inactive:
inactive=1h
: 如果缓存的数据在指定的时间段内(这里是1小时)没有被访问,则会被自动删除。这有助于确保不常用的内容不会长时间占用磁盘空间。
5️⃣ max_size:
max_size=512m
: 这是缓存可以使用的磁盘空间的最大值。在这种情况下,缓存最大可以使用512MB。当达到这个上限时,Nginx 将开始删除最老的缓存文件。
6️⃣ use_temp_path:
use_temp_path=off
: 默认情况下,当从上游服务器接收响应时,Nginx 会首先将其写入一个临时路径,然后再移动到缓存路径。这个指令禁用这种行为,使得响应直接写入缓存路径,从而减少文件操作和潜在的磁盘I/O。
🌍 启用 Nginx 代理缓存
启用 Nginx 的代理缓存是一个关键步骤,它允许你为特定的 location
块缓存上游服务器的响应。以下是这部分配置的详细解释和完整示例:
📌 示例配置:
location / {
...
# 定向请求到上游服务器
proxy_pass http://www.example.com;
# 使用先前定义的缓存区域 "the_cache_zone"
proxy_cache the_cache_zone;
# 添加一个响应头来显示缓存的状态 (例如: HIT, MISS, BYPASS)
add_header X-Cache-Status $upstream_cache_status;
...
}
📌配置详解:
1️⃣ proxy_pass http://www.example.com;
:
- 这一行指示 Nginx 将传入的请求转发到
www.example.com
上游服务器。
2️⃣ proxy_cache the_cache_zone;
:
- 这告诉 Nginx 使用我们在之前的
proxy_cache_path
指令中定义的 “the_cache_zone” 缓存区域。
3️⃣ add_header X-Cache-Status $upstream_cache_status;
:
- 这会在响应中添加一个名为
X-Cache-Status
的头,它显示了缓存的状态。这对于调试和监控缓存的效果非常有用。可能的值有:- HIT: 请求的内容在缓存中被找到,并且是新鲜的。
- MISS: 请求的内容不在缓存中,或者缓存的内容是过时的。
- BYPASS: 请求被配置为绕过缓存。
🚫 忽略上游缓存指令
如果你想确保从源站抓取的内容总是新鲜的,你可以忽略上游的缓存指令,并设置自己的缓存有效期。
📌 示例配置:
location / {
...
# 忽略上游服务器发送的特定缓存相关的响应头
proxy_ignore_headers X-Accel-Expires Cache-Control Expires;
# 设置不同的 HTTP 响应状态码的缓存有效期
proxy_cache_valid 301 1h; # 永久重定向缓存1小时
proxy_cache_valid 200 30m; # 成功的响应缓存30分钟
proxy_cache_valid any 1m; # 任何其他响应状态码缓存1分钟
# 如果上游响应包含“Etag”或“Last-Modified”头,则进行缓存重新验证
proxy_cache_revalidate on;
...
}
📌 配置详解:
1️⃣ proxy_ignore_headers
:
- 该指令告诉 Nginx 忽略上游服务器发送的指定的缓存相关响应头。这确保无论上游服务器如何设置缓存策略,Nginx 都会使用你定义的缓存策略。
2️⃣ proxy_cache_valid
:
- 该指令定义了对于不同的 HTTP 响应状态码,缓存应该保持有效多久。例如,你可能希望缓存 200 OK 响应30分钟,但只缓存 404 Not Found 响应1分钟。
3️⃣ proxy_cache_revalidate
:
- 当这个指令设置为“on”时,Nginx 会在缓存的内容即将过期时向上游服务器发送一个请求,检查内容是否已经更改。如果上游响应表明内容没有更改(例如,通过发送 304 Not Modified 响应),Nginx 将更新缓存的过期时间,而不是重新获取整个内容。
💚 防止缓存雪崩策略
缓存雪崩是指当大量缓存项同时到期或失效时,大量的请求直接涌向源站,可能导致源站短时间内超负荷运行或崩溃。这通常是因为大量数据被同时缓存,然后在同一时间点到期。Nginx 提供了一系列指令来帮助缓解这种情况。以下是这部分配置的详细解释:
📌 示例配置:
location / {
...
# 启用缓存锁,确保对特定资源的请求只有一个可以访问源站
proxy_cache_lock on;
# 在以下情况下使用陈旧(过期)的缓存数据:源站错误、超时、正在更新缓存、源站返回503状态码
proxy_cache_use_stale error timeout updating http_503;
# 即使返回过期的缓存数据,也会在后台与源站更新缓存
proxy_cache_background_update on;
...
}
📌 配置详解:
1️⃣ proxy_cache_lock
:
- 当该指令设置为
on
时,对于同一资源的新请求,如果已经有一个请求正在回源获取数据,则其他请求会等待。这确保了在缓存失效的情况下,只有一个请求会去源站获取数据,而其他请求将等待这个请求完成并使用其缓存的数据。
2️⃣ proxy_cache_use_stale
:
- 该指令指定了在哪些情况下 Nginx 应该使用过期的缓存数据。例如,如果源站发生错误、请求超时、正在更新缓存或源站返回503状态码时,Nginx 会返回过期的缓存数据,而不是直接去源站获取数据。
3️⃣ proxy_cache_background_update
:
- 当这个指令设置为
on
时,即使 Nginx 为客户端返回了过期的缓存数据,它也会在后台与源站交互来更新缓存。这确保了客户端能够快速获取响应,同时缓存也能保持最新。
🔄 手动清除缓存策略
清除特定的缓存条目可以是一个有用的功能,特别是当内容发生更改并且你希望立即反映这些更改,而不是等待缓存自然过期。ngx_cache_purge
是一个第三方模块,可以轻松地实现这个功能在 Nginx 中。以下是这部分配置的详细解释:
📌 示例配置:
location / {
...
# 指定该 location 使用的缓存区域
proxy_cache the_cache_zone;
...
}
location ~ /purge(/.*) {
...
# 仅允许本地服务器清除缓存,其他所有请求都被拒绝
allow 127.0.0.1;
deny all;
# 清除指定的缓存条目
proxy_cache_purge the_cache_zone $scheme$proxy_host$1$is_args$args;
...
}
📌 配置详解:
1️⃣ proxy_cache
:
- 在主 location 中定义使用的缓存区域。
2️⃣ location ~ /purge(/.*)
:
- 这是一个正则匹配的 location,用于捕获以
/purge/
开头的请求。这些请求是用于清除缓存的。
3️⃣ allow 127.0.0.1; deny all;
:
- 这确保只有从本地服务器发出的请求可以清除缓存。这是一个安全措施,确保外部用户不能随意清除你的缓存。
4️⃣ proxy_cache_purge
:
- 该指令指定要清除的缓存条目。它使用
$scheme$proxy_host$1$is_args$args
作为键来查找和清除缓存,其中$1
是捕获的路径。
要注意,为了使这个配置工作,你需要先安装 ngx_cache_purge
模块。在安装和配置之后,你可以通过向 /purge/your_path
发送请求来清除特定路径下的缓存条目。例如,为了清除 /images/my_image.jpg
的缓存,你可以请求 /purge/images/my_image.jpg
。
🌐 Nginx 缓存清理
Nginx 提供了缓存功能,可以大大提高请求的响应速度,但同时也需要提供有效的缓存管理机制。清理过期或不再需要的缓存是缓存管理的关键部分。这可以通过使用 HTTP PURGE
方法和 ngx_cache_purge
模块实现。
💡 配置缓存清除:
-
定义清除方法:
在http {}
上下文中定义一个新变量,例如$purge_method
,来检测使用的请求方法。http { ... map $request_method $purge_method { PURGE 1; default 0; } }
-
启用缓存清除:
在 server 块的相应 location 中,配置proxy_cache_purge
指令来响应清除请求。server { listen 80; server_name www.example.com; location / { proxy_pass http://localhost:8002; proxy_cache mycache; proxy_cache_purge $purge_method; } }
🚀 发送清除命令:
一旦配置了 proxy_cache_purge
,你可以发送特定的 PURGE
请求来清除缓存。例如,使用 curl
:
$ curl -X PURGE -D - "http://www.example.com/*"
🔒 限制清除命令的访问:
为了增加安全性,建议限制发送清除请求的 IP 地址。
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 中, 尽管缓存文件可能会因为某些原因(例如过期)而不再被访问, 但这并不意味着它们会立即从磁盘上删除。这些文件可能会继续占用磁盘空间,直到由于某些原因(如达到 max_size
限制)而被删除。为了更有效地管理这些缓存文件, 并确保及时删除不再需要的文件, NGINX 提供了一个特殊的清除进程。
🛠️ 配置方法:
-
定义缓存路径并激活清除进程:
在http
上下文中, 你需要定义你的缓存路径,并在proxy_cache_path
指令中使用purger
参数来激活清除进程。http { ... proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on; ... }
这个 purger=on
参数会激活一个后台进程, 该进程会定期迭代所有缓存条目并删除过期或不再需要的文件。
🌀 清除进程的工作原理:
当你激活清除进程后, 它会定期检查缓存目录,并根据各种参数(如 inactive
)来确定哪些缓存条目应该被删除。这确保了你的缓存目录不会因为过期的或不再需要的文件而变得臃肿。
例如, 如果你设置了 inactive=1h
, 那么任何在过去一小时内都没有被访问的缓存文件都会被清除进程删除。
此外, 如果你的缓存目录达到了 max_size
限制, 清除进程还会根据文件的最后访问时间来删除文件, 直到缓存大小再次低于 max_size
限制。
⚠️ 注意事项:
- 清除进程只会删除那些不再需要的缓存文件, 它不会影响当前活跃的或新生成的缓存条目。
- 为了确保缓存清除的高效性和准确性, 建议定期监控和管理你的缓存目录, 确保它不会过快地增长或被不必要的文件填满。
📦 字节范围缓存:
在处理大文件,尤其是多媒体文件(如视频和音频)时,用户或客户端可能只请求文件的一部分。这种部分请求通常是为了支持断点续传或适应带宽限制。NGINX 的 Cache Slice 模块允许你缓存这些部分请求,从而提高效率和响应速度。
🌐 工作原理:
-
切片 (Slicing):
当一个大文件被请求时,而不是一次性下载和缓存整个文件,NGINX 会将文件分成多个小块或“切片”。这样,当客户端请求文件的某一部分时,只需从缓存中检索所需的“切片”。 -
按需缓存:
只有被请求的切片才会被缓存,这避免了缓存大量不必要的数据。例如,如果用户只观看了视频的前10分钟,那么只有这10分钟的数据会被缓存。 -
逐步填充:
当新的部分请求到来时,新的切片会被添加到缓存中。这意味着,随着时间的推移,整个文件可能会逐渐被缓存,但只在需要的时候。
💡 示例解析:
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;
}
-
slice 1m;
: 这指示 NGINX 将文件切割成 1MB 的块进行缓存。 -
proxy_cache cache;
: 使用名为“cache”的缓存定义。 -
proxy_cache_key $uri$is_args$args$slice_range;
: 定义缓存键,确保每个切片都有其唯一的键。 -
proxy_set_header Range $slice_range;
: 将请求的范围传递给上游服务器,以便只请求所需的数据块。 -
proxy_cache_valid 200 206 1h;
: 指定 HTTP 200 和 206 响应的缓存有效期为1小时。
⚠️ 注意事项:
-
使用 Cache Slice 模块时,应确保源服务器支持范围请求。这通常是通过检查服务器的响应头部中是否有“Accept-Ranges”来确定的。
-
切片缓存最适用于大型、不经常更改的文件。如果文件经常变动,可能需要更频繁地更新缓存,这可能会减少切片缓存的效果。
🎛️ 综合配置示例解析
http {
# 定义缓存路径和参数
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m max_size=512m inactive=1h use_temp_path=off;
# 根据请求方法确定是否执行缓存清除操作
map $request_method $purge_method {
PURGE 1;
default 0;
}
# 限制能执行缓存清除的 IP 地址
geo $purge_allowed {
default 0;
10.0.0.1 1;
192.168.0.0/24 1;
}
server {
listen 80;
server_name www.example.com;
# 基本缓存配置
location / {
proxy_pass http://backend;
proxy_cache mycache;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 30m;
add_header X-Cache-Status $upstream_cache_status;
# 清除缓存
proxy_cache_purge $purge_method;
}
# 忽略上游的缓存指令并设置自己的缓存期限
location /fresh-content {
proxy_pass http://backend;
proxy_cache mycache;
proxy_ignore_headers X-Accel-Expires Cache-Control Expires;
proxy_cache_valid 301 1h;
proxy_cache_valid 200 30m;
proxy_cache_valid any 1m;
proxy_cache_revalidate on;
}
# 防止缓存雪崩配置
location /popular-content {
proxy_pass http://backend;
proxy_cache mycache;
proxy_cache_lock on;
proxy_cache_use_stale error timeout updating http_503;
proxy_cache_background_update on;
}
# 字节范围缓存配置
location /large-files {
slice 1m;
proxy_pass http://backend;
proxy_cache mycache;
proxy_cache_key $uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_cache_valid 200 206 1h;
}
}
}
🌐 全局配置:
-
proxy_cache_path
: 🗂️ 定义了缓存的存储路径/data/nginx/cache
。此指令明确了采用的是两级目录结构(由levels=1:2
确定),缓存的大小(max_size=512m
),非活动缓存的过期时间(inactive=1h
),以及明确了不使用临时路径存储正在写入的缓存数据(use_temp_path=off
)。 -
🌟 两个
map
块是决策利器。第一个根据请求的方法决定是否清除缓存,第二个根据客户端的 IP 地址决定是否允许清除缓存操作。
🏢 Server 配置:
- 在
server
块内, 🎧 您的 Nginx 服务器配置为监听 80 端口,并为www.example.com
域名提供服务。
📍 Location 配置:
-
🛍️ 基本缓存配置:
- 🎯 这是一个普通的缓存配置,适用于绝大多数请求。所有匹配此位置的请求都会被代理到
http://backend
。 proxy_cache
🏷️ 指定了要使用的缓存区域(即之前定义的mycache
)。proxy_cache_key
🗝️ 为请求定义了生成缓存键的方式。- ⏲️ 一个特定的缓存条目将在 HTTP 响应状态码 200 后的 30 分钟内被视为有效。
add_header
📌 用于在响应中添加一个X-Cache-Status
头,这有助于调试,因为它告诉您请求是否被缓存。
- 🎯 这是一个普通的缓存配置,适用于绝大多数请求。所有匹配此位置的请求都会被代理到
-
🚫 忽略上游的缓存指令:
- 🔄 这部分为那些始终需要从后端获取最新内容的请求而设计。
- 🛑 使用
proxy_ignore_headers
指令来忽略上游服务器的缓存相关头。 - 📅 根据 HTTP 响应状态码设置了不同的缓存有效期。
-
❄️ 防止缓存雪崩配置:
- 🛡️ 这部分是为了处理可能有大量并发请求的热门内容。
proxy_cache_lock
🔒 确保对于同一个资源,在缓存未命中时只有一个请求传递到后端。proxy_cache_use_stale
🔄 允许在某些错误情况下使用过期的缓存内容。proxy_cache_background_update
🌌 指示 NGINX 在后台更新过期的缓存。
-
📦 字节范围缓存配置:
- 🎞️ 这部分是为了处理大文件的部分请求。
slice
🔪 将文件划分为大小为 1M 的片段或"切片"。proxy_set_header Range $slice_range;
📤 确保范围请求传递给后端服务器。
🛠️ 如何配置 Nginx 作为 CDN 的边缘节点?
🌐 CDN (内容分发网络 | Content Delivery Network)
CDN 是一个由多个服务器组成的分布式网络。这些服务器分散在全球各地,旨在优化内容的传送。其核心功能如下:
- 减少延迟 🚀: 由于用户可以从地理位置上较近的服务器获取内容,所以响应时间更短。
- 增加下载速度 ⚡: 多个分散的服务器可以处理大量的用户请求,从而增加整体的响应速度。
- 提高可用性和容错性 💡: 如果一个服务器出现问题,流量可以被重定向到其他健康的服务器。
- 降低原始服务器的负载 🏋️♂️: 将流量分发到各个服务器可以减少原始服务器的压力。
📚 结构:
CDN 主要由两部分组成:
- 边缘服务器 🌐: 存储内容的复制品,为用户提供快速访问。
- 原始服务器 💽: 存储原始的、未修改的内容。
当用户👥 请求某个内容时,他们将从最接近的边缘服务器上获得响应,这通常基于用户的地理位置或网络状况来确定。
-
安装 Nginx 📦
- 在大多数 Linux 发行版上,你可以使用默认的包管理器安装 Nginx。例如,在 Ubuntu 上,你可以使用以下命令:
sudo apt update sudo apt install nginx
- 在大多数 Linux 发行版上,你可以使用默认的包管理器安装 Nginx。例如,在 Ubuntu 上,你可以使用以下命令:
-
配置 Nginx ⚙️
- 编辑 Nginx 的默认配置文件:
sudo nano /etc/nginx/sites-available/default
- 然后,你可以添加以下内容来配置缓存:
server { listen 80; server_name cdn.example.com; location / { proxy_pass http://your_backend_server_address; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 开启缓存 proxy_cache one; proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args"; proxy_cache_valid 200 302 60m; proxy_cache_valid 404 1m; } # 定义缓存路径和细节 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:10m inactive=60m; proxy_temp_path /var/cache/nginx/tmp; }
- 编辑 Nginx 的默认配置文件:
-
启动 Nginx 🚀
- 使用以下命令启动或重启 Nginx 服务:
sudo systemctl restart nginx
- 使用以下命令启动或重启 Nginx 服务:
📘 解释:
-
🖥
proxy_pass
指令告诉 Nginx 将请求转发到后端服务器。 -
📩
proxy_set_header
指令确保转发给后端服务器的请求包含正确的头信息。 -
💾
proxy_cache
和相关指令配置 Nginx 如何缓存从后端服务器接收的内容。proxy_cache_key
定义了如何为缓存的内容生成键。 -
🗂
proxy_cache_path
定义了缓存内容的存储位置和一些关于如何管理缓存的细节。