Nginx 超时后强制重新验证过期缓存

Nginx 超时后强制重新验证过期缓存

Nginx 反向代理缓存使用中有一个情况,当;

proxy_cache_background_update on;
proxy_cache_use_stale updating;

对于同一个 URL,如果一个响应来自上游并且具有 max-age,而所有其他响应都为 no-cache,那么 Nginx 将永远无法从这种情况中恢复。

想象一下这样的场景:

  1. 客户端 -> Nginx(MISS) -> 上游200(缓存控制:无缓存)
  2. 客户端 -> Nginx(MISS) -> 上游200(缓存控制:无缓存)
  3. 客户端 -> Nginx(MISS) -> 上游200(缓存控制:无缓存)
  4. 客户端 -> Nginx(MISS) -> 上游503(缓存控制:最大年龄=10)
  5. 客户端 -> Nginx (HIT,503,年龄:3)
  6. 客户端 -> Nginx (HIT,503,年龄:8岁)
  7. 客户端 -> Nginx (陈旧,503,年龄:13岁)->保利上游200 (缓存控制:无缓存)
  8. 客户端 -> Nginx (陈旧,503,年龄:18岁)->保利上游200 (缓存控制:无缓存)
  9. 客户端 -> Nginx (陈旧,503,年龄:23​​岁)->保利上游200 (缓存控制:无缓存)
  10. ... 客户看到503永恒

在上述场景中,上游发生了一次错误,并返回了 max-age(不幸的是,这种行为无法干预)。因为真正的 200 响应是 no-cache,所以它永远无法覆写STALE 503 并永远给出错误直到手动清除。

在网上找不到关于这种情况的任何信息,所以我在这里问。如何处理这个问题。我正在使用OpenResty因此我就可以访问 Nginx 开源模块和 Lua。

可能的解决方案和我的研究:

  • stale-if-errorCache-Control 标头的扩展stale-while-revalidate似乎确实解决了这个问题。不幸的是,上游标头不允许修改(而且在 Nginx 处理标头之前,没有办法像预期的那样以黑客方式插入这些标头)。

  • 使用 Lua 脚本手动设置 STALE 缓存的超时时间,并在超时后清除缓存。但如果标准/Nginx 提供了解决方案,我更愿意使用它。

  • 添加第二个反向代理来添加标题stale-if-errorstale-while-revalidate默认(我宁愿让问题存在,而不是这样做)。

  • 使用 Lua 跟踪缓存期限,如果超过则设置变量为 true,然后proxy_cache_bypass从 Nginx 中使用它。(有点灰色区域,执行顺序与内容阶段指令有关)

相关内容