资讯专栏INFORMATION COLUMN

Nginx 是如何让你的缓存延期的

silvertheo / 541人阅读

摘要:所以总体上该响应会被缓存两小时。其次,这个算是一般的多层缓存固有的弊端缓存数据的最大过期时间,取决于各级缓存的总和。这种情况下,缓存只是作为一个临时救急的方案使用,我们并不希望多缓存更多的时间。

当 Nginx 使用 proxy cache 的文件作为响应时,它会更新其中的一些内容,比如 Date 响应头;但大部分响应头都不会得到更新,比如 Expires 和 Cache-Control。众所周知,Cache-Control 可以通过 max-age=xxx 或者 s-maxage=xxx 指令设置缓存的有效时间。跟 Expires 响应头不同,这一时间是相对的。假设上游服务器返回 Cache-Control: public; max-age=3600,那么 Nginx 会缓存该响应一小时。如果在这一小时到期之前,Client 访问了 Nginx,它会获取到同样的 Cache-Control 响应头,因此会再缓存多一小时。所以总体上该响应会被缓存两小时。

这听起来很让人惊讶。但仔细想想,其实也不算什么严重的问题。首先,当我们设置 max-age=3600 时,大多数情况下并不要求其严格地在一小时后过期。其次,这个算是一般的多层缓存固有的弊端:缓存数据的最大过期时间,取决于各级缓存 TTL 的总和。如果想要避免,你可以选择根据外层数据剩下的 TTL 设置当前 TTL;或者提供主动 purge 的操作,从最内层开始逐层清理数据。

当然,某些时候下,这一行为会带来一些问题。举个例子,假设我们开启了 proxy_cache_use_stale,在上游服务器出问题时使用过期的内容代替正常的响应。这种情况下,缓存只是作为一个临时救急的方案使用,我们并不希望 Client 多缓存更多的时间。否则会有上游应用的开发者抱怨,为何上游服务器已经正常了,用户刷新页面看到的还是旧数据。作为解决办法,我们可以在 Nginx 的 header filter 阶段,通过 Lua 代码或者 Nginx C module,把 Cache-Control: max-age=... 修改成 Cache-Control: no-cache。这么一来,Client 会在使用缓存之前先验证下,如果 Nginx 返回 304 状态码,那么该缓存会被继续使用;如果上游已经 OK 了且更新了响应,那么 Client 就会重新请求,避免使用过期的内容。

这里需要强调下,no-cache 并非如字面上的意义表示不缓存,而是要求 Client 在使用该缓存之前,需要先验证下被缓存的内容是否还是最新的。MDN 的说法是:

Forces caches to submit the request to the origin server for validation before releasing a cached copy.

对应的,RFC 7234 的说法:

The "no-cache" request directive indicates that a cache MUST NOT use
a stored response to satisfy the request without successful
validation on the origin server.

如果要想让 Client 不缓存响应的内容,按 MDN 上的说法,需要用 Cache-Control: no-cache, no-store, must-revalidate(https://developer.mozilla.org...)。

仔细看了下 no-cache / no-store / must-revalidate 这三项指令的介绍,似乎 no-store 就能让 Client 不用这个缓存,因为 no-store 要求:

The cache should not store anything about the client request or server response.

另外 must-revalidate 要求在使用过期缓存前验证下该内容是否是最新的,而 no-cache 也是要求重新验证的,那为什么需要两个都一起用呢?

Google 搜索把我带到了这个 SO 问答:https://stackoverflow.com/que...。这个回答里面解释了为何不单单用 no-store:因为臭名昭著的 IE6 浏览器在处理 no-store 时有 bug。但可惜的是,这个回答没有给出这一论断的证据,比如 IE 的 bug report 之类。MDN 在给出 Cache-Control: no-cache, no-store, must-revalidate 这个例子的时候,也没有提及更多的上下文。这很像没有任何注释的老代码:我们不知道当初为何这么写,而把它删掉似乎不会带来什么问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40259.html

相关文章

  • 入职5个月延期转正,每天加班到22点,妹子直接被逼走了?这职场PUA听得我拳头都硬了。。。

    摘要:入职半年之后,老板给他签期权合同,签完后,老板说股份需要董事会签字,先把合同收回去。且因为长年加班,得了一身病。多次实验之后,实验者把狗笼打开,这时候蜂音器响了,狗狗不但不逃,反而倒地呻吟和颤抖,等待电击的到来。 ...

    joyqi 评论0 收藏0
  • 教你用认知和人性来做最棒程序员

    摘要:不久前,在团队内部和大家做了一次分享,内容就是这次要讲的用认知和人性来提升自己的技术水平,大家反响不错,所以这次整理一下也分享给大家。 不久前,在团队内部和大家做了一次分享,内容就是这次要讲的用认知和人性来提升自己的技术水平,大家反响不错,所以这次整理一下也分享给大家。最初我是想用借优秀的产品经理思维来做最棒程序员的这个标题,但想想还是要有同理心,技术同学平时和产品同学已经是相爱相杀了...

    Scliang 评论0 收藏0
  • 教你用认知和人性来做最棒程序员

    摘要:不久前,在团队内部和大家做了一次分享,内容就是这次要讲的用认知和人性来提升自己的技术水平,大家反响不错,所以这次整理一下也分享给大家。 不久前,在团队内部和大家做了一次分享,内容就是这次要讲的用认知和人性来提升自己的技术水平,大家反响不错,所以这次整理一下也分享给大家。最初我是想用借优秀的产品经理思维来做最棒程序员的这个标题,但想想还是要有同理心,技术同学平时和产品同学已经是相爱相杀了...

    Kosmos 评论0 收藏0
  • 利用 NGINX 最大化 Python 性能,第二部分:负载均衡和监控

    摘要:现有的服务器和应用程序服务器相结合并在一个冒泡中运行,无法直接接触网络流量,由反向代理服务器提出填鸭式请求。赋予高可用性让你的反向代理服务器镜像到在线备份,同时拥有备用的应用程序服务器,让你的站点高度可用。 【编者按】本文主要介绍 NGINX 的主要功能以及如何通过 Nginx 优化 Python 应用性能。本文系国内 ITOM 管理平台 OneAPM 编译呈现。 本文上一篇系: 利用...

    zhangrxiang 评论0 收藏0
  • 利用 NGINX 最大化 Python 性能,第二部分:负载均衡和监控

    摘要:现有的服务器和应用程序服务器相结合并在一个冒泡中运行,无法直接接触网络流量,由反向代理服务器提出填鸭式请求。赋予高可用性让你的反向代理服务器镜像到在线备份,同时拥有备用的应用程序服务器,让你的站点高度可用。 【编者按】本文主要介绍 NGINX 的主要功能以及如何通过 Nginx 优化 Python 应用性能。本文系国内 ITOM 管理平台 OneAPM 编译呈现。 本文上一篇系: 利用...

    Snailclimb 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<