Nginx边缘缓存+云存储回源的核心是proxy_cache+proxy_store+error_page组合:Nginx只调度缓存与回源,对象存储负责内容存储,实现静态资源就近缓存、未命中自动拉取、零文件上传、大文件分片支持。

用 Nginx 做边缘缓存 + 云存储回源托管,不是要堆配置,而是把“缓存决策权”交给 Nginx,“内容存储权”交给对象存储(如阿里云 OSS、腾讯 COS、AWS S3),两者配合做到:静态资源就近缓存、未命中自动回源拉取、无需上传文件到服务器、支持大文件分片和断点续传——关键在 proxy_cache + proxy_store + 自定义 error_page 回源逻辑 的组合使用。
一、核心思路:Nginx 不存文件,只管缓存调度与回源中转
Nginx 本身不作为长期存储节点,而是:
- 接收用户请求,先查本地缓存(
proxy_cache); - 命中则直接返回,不触达后端;
- 未命中时,不报 404,而是触发
error_page 404 = @fetch_from_oss; - 由
@fetch_from_osslocation 调用云存储的预签名 URL 或直连 endpoint 拉取资源,并用proxy_store on自动落盘缓存; - 后续相同请求即可命中本地磁盘缓存,实现“首次回源、二次秒开”。
二、基础配置:启用缓存区与代理策略
在 http 块中定义缓存路径与策略:
proxy_cache_path /var/cache/nginx/oss_cache levels=1:2 keys_zone=oss_cache:10m max_size=50g inactive=7d use_temp_path=off;
说明:
-
levels=1:2表示两级目录哈希,防止单目录文件过多; -
keys_zone=oss_cache:10m内存中缓存 key 元信息,10MB 可存约 8 万条; -
max_size=50g磁盘缓存上限,超出后按 LRU 清理; -
inactive=7d7 天未被访问的缓存自动过期; -
use_temp_path=off避免写临时文件再 rename,提升写入效率。
三、关键 location:缓存服务 + 回源拉取双模式
假设你对外提供 /static/xxx.png,实际资源存在 COS 桶 https://my-bucket.cos.ap-beijing.myqcloud.com/xxx.png:
location /static/ {
# 启用缓存
proxy_cache oss_cache;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
<pre class="brush:php;toolbar:false;"># 缓存键定制(避免参数干扰静态资源)
proxy_cache_key "$scheme$request_method$host$uri";
# 尝试读取本地缓存
proxy_cache_bypass $arg_nocache;
proxy_no_cache $arg_nocache;
# 未命中时交由 @fetch_from_oss 处理
proxy_intercept_errors on;
error_page 404 = @fetch_from_oss;
# 直接返回缓存(不转发给后端)
proxy_pass https://dummy-upstream; # 占位,实际不走这里
}
注意:proxy_pass 指向一个无效 upstream 是故意的——因为我们要靠 error_page 404 触发回源,而不是让 Nginx 默认去 upstream 找。
四、回源逻辑:@fetch_from_oss 实现“按需拉取 + 自动缓存”
在同级 server 或 http 块中添加:
location @fetch_from_oss {
internal; # 仅限内部跳转,禁止外部直接访问
<pre class="brush:php;toolbar:false;"># 构造 COS 对象 URL(示例为腾讯云 COS,其他云厂商替换域名和鉴权方式)
set $bucket "my-bucket.cos.ap-beijing.myqcloud.com";
set $object_uri "$1"; # 提取 /static/(.*) 中的路径
rewrite ^/static/(.*)$ /$1 break;
# 关键:proxy_store 会把响应体原样保存到文件系统,路径由 proxy_store 指令 + URI 决定
proxy_store /var/cache/nginx/oss_cache/$bucket$uri;
proxy_store_access user:rw group:rw all:rw;
# 回源请求(无鉴权时可直连;有签名需用 auth_request 或 Lua 拼接)
proxy_pass https://$bucket$uri;
proxy_set_header Host $bucket;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
# 支持大文件分片传输
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection '';
}
补充说明:
-
internal确保该 location 不会被外部绕过缓存直接调用; -
proxy_store是“自动落盘”的核心——它不依赖proxy_cache,而是根据 URI 映射到磁盘路径并写入原始响应体; - 若云存储要求签名(如 OSS 临时 token),可用
ngx_http_lua_module在@fetch_from_oss中动态生成带参 URL,或前置部署签名网关; - 对于视频、大附件等,建议开启
proxy_buffering off配合chunked流式传输,避免内存积压。
五、上线前必验:缓存是否生效?回源是否可控?
用 curl 验证行为链路:
- 首次请求:
curl -I https://yoursite.com/static/test.jpg→ 查看响应头是否有X-Cache: MISS(自定义 header)+Age: 0; - 再次请求同一资源 → 应出现
X-Cache: HIT+Age: 120(表示已缓存 120 秒); - 手动删掉
/var/cache/nginx/oss_cache/...下对应文件 → 第三次请求应再次MISS并成功回源重建; - 请求一个 COS 上不存在的路径 → 应返回 404(非 500),且 Nginx error log 中出现
upstream sent no valid response或 COS 返回的 404,证明回源链路通。
不复杂但容易忽略:务必检查 /var/cache/nginx/oss_cache 目录权限(nginx worker 用户需有读写权),以及磁盘空间、inodes 是否充足。










