对于您的站点的访问者来说,智能化的内容缓存是提高用户体验最有效的方式之一。缓存,或者对之前的请求的临时存储,是HTTP协议实现中最核心的内容分发策略之一。分发路径中的组件均可以缓存内容来加速后续的请求,这受控于对该内容所声明的缓存策略。
在这份指南中,我们将讨论一些Web内容缓存的基本概念。这主要包括如何选择缓存策略以保证互联网范围内的缓存能够正确的处理您的内容。我们将谈一谈缓存带来的好处、副作用以及不同的策略能带来的性能和灵活性的最大结合。
缓存(caching)是一个描述存储可重用资源以便加快后续请求的行为的术语。有许多不同类型的缓存,每种都有其自身的特点,应用程序缓存和内存缓存由于其对特定回复的加速,都很常用。
这份指南的主要讲述的Web缓存是一种不同类型的缓存。Web缓存是HTTP协议的一个核心特性,它能最小化网络流量,并且提升用户所感知的整个系统响应速度。内容从服务器到浏览器的传输过程中,每个层面都可以找到缓存的身影。
Web缓存根据特定的规则缓存相应HTTP请求的响应。对于缓存内容的后续请求便可以直接由缓存满足而不是重新发送请求到Web服务器。
有效的缓存技术不仅可以帮助用户,还可以帮助内容的提供者。缓存对内容分发带来的好处有:
在面对缓存时,您可能对一些经常遇到的术语可能不太熟悉。一些常见的术语如下:
还有许多其他的缓存术语,不过上面的这些应该能帮助您开始。
某些特定的内容比其他内容更容易被缓存。对大多数站点来说,一些适合缓存的内容如下:
这些文件更倾向于不经常改变,所以长时间的对它们进行缓存能获得好处。
一些项目在缓存中必须加以注意:
一些内容从来不应该被缓存:
除上面的通用规则外,通常您需要指定一些规则以便于更好地缓存不同种类的内容。例如,如果登录的用户都看到的是同样的网站视图,就应该在任何地方缓存这个页面。如果登录的用户会在一段时间内看到站点中用户特定的视图,您应该让用户的浏览器缓存该数据而不应让任何中介节点缓存该视图。
Web内容会在整个分发路径中的许多不同的位置被缓存:
上面的这些位置通常都可以根据它们自身的缓存策略和内容源的缓存策略缓存一些相应的内容。
缓存策略依赖于两个不同的因素。所缓存的实体本身需要决定是否应该缓存可接受的内容。它可以只缓存部分可以缓存的内容,但不能缓存超过限制的内容。
缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。这些策略主要通过特定的HTTP头部来清晰地表达。
经过几个不同HTTP协议的变化,出现了一些不同的针对缓存方面的头部,它们的复杂度各不相同。下面列出了那些你也许应该注意的:
Expires
**:尽管使用范围相当有限,但 Expires
头部是非常简洁明了的。通常它设置一个未来的时间,内容会在此时间过期。这时,任何对同样内容的请求都应该回到原始服务器处。这个头部或许仅仅最适合回退模式(fall back)。 Cache-Control
**:这是 Expires
的一个更加现代化的替换物。它已被很好的支持,且拥有更加灵活的实现。在大多数案例中,它比 Expires
更好,但同时设置两者的值也无妨。稍后我们将讨论您可以设置的 Cache-Control
的详细选项。 ETag
**: ETag
用于缓存验证。源服务器可以在首次服务一个内容时为该内容提供一个独特的 ETag
。当一个缓存需要验证这个内容是否即将过期,他会将相应的 ETag
发送回服务器。源服务器或者告诉缓存内容是一致的,或者发送更新后的内容(带着新的 ETag
)。 Last-Modified
:这个头部指明了相应的内容最后一次被修改的时间。它可能会作为保证内容新鲜度的验证策略的一部分被使用。 Content-Length
**:尽管并没有在缓存中明确涉及, Content-Length
头部在设置缓存策略时很重要。某些软件如果不提前获知内容的大小以留出足够空间,则会拒绝缓存该内容。 Vary
**:缓存系统通常使用请求的主机和路径作为存储该资源的键。当判断一个请求是否是请求同样内容时, Vary
头部可以被用来提醒缓存系统需要注意另一个附加头部。它通常被用来告诉缓存系统同样注意 Accept-Encoding
头部,以便缓存系统能够区分压缩和未压缩的内容。 Vary
头部提供给您存储同一个内容的不同版本的能力,代价是降低了缓存的容量。
在使用 Accept-Encoding
时,设置 Vary
头部允许明确区分压缩和未压缩的内容。这在服务某些不能处理压缩数据的浏览器时很重要,它可以保证基本的可用性。 Vary
的一个典型的值是 Accept-Encoding
,它只有两到三个可选的值。
一开始看上去 User-Agent
这样的头部可以用于区分移动浏览器和桌面浏览器,以便您的站点提供差异化的服务。但 User-Agent
字符串是非标准的,结果将会造成在中间缓存中保存同一内容的许多不同版本的缓存,这会导致缓存命中率的降低。 Vary
头部应该谨慎使用,尤其是您不具备在您控制的中间缓存中使请求标准化的能力(也许可以,比如您可以控制CDN的话)。
上面我们提到了 Cache-Control
头部如何被用与现代缓存策略标准。能够通过这个头部设定许多不同的缓存指令,多个不同的指令通过逗号分隔。
一些您可以使用的指示内容缓存策略的 Cache-Control
的选项如下:
no-cache
:这个指令指示所有缓存的内容在新的请求到达时必须先重新验证,再发送给客户端。这条指令实际将内容立刻标记为过期的,但允许通过验证手段重新验证以避免重新下载整个内容。 no-store
:这条指令指示缓存的内容不能以任何方式被缓存。它适合在回复敏感信息时设置。 public
:它将内容标记为公有的,这意味着它能被浏览器和其他任何中间节点缓存。通常,对于使用了HTTP验证的请求,其回复被默认标记为 private
。 public
标记将会覆盖这个设置。 private
:它将内容标记为私有的。私有数据可以被用户的浏览器缓存,但 不能 被任何中间节点缓存。它通常用于用户相关的数据。 max-age
:这个设置指示了缓存内容的最大生存期,它在最大生存期后必须在源服务器处被验证或被重新下载。在现代浏览器中这个选项大体上取代了 Expires
头部,浏览器也将其作为决定内容的新鲜度的基础。这个选项的值以秒为单位表示,最大可以表示一年的新鲜期(31536000秒)。 s-maxage
:这个选项非常类似于 max-age
,它指明了内容能够被缓存的时间。区别是这个选项只在中间节点的缓存中有效。结合这两个选项可以构建更加灵活的缓存策略。 must-revalidate
:它指明了由 max-age
、 s-maxage
或 Expires
头部指明的新鲜度信息必须被严格的遵守。它避免了缓存的数据在网络中断等类似的场景中被使用。 proxy-revalidate
:它和上面的选项有着一样的作用,但只应用于中间的代理节点。在这种情况下,用户的浏览器可以在网络中断时使用过期内容,但中间缓存内容不能用于此目的。 no-transform
:这个选项告诉缓存在任何情况下都不能因为性能的原因修改接收到的内容。这意味着,缓存不允许压缩接收到的内容(没有从原始服务器处接收过压缩版本的该内容)并发送。 这些选项能够以不同的方式结合以获得不同的缓存行为。一些互斥的值如下:
no-cache
, no-store
以及由其他前面未提到的选项指明的常用的缓存行为 public
和 private
如果 no-store
和 no-cache
都被设置,那么 no-store
会取代 no-cache
。对于非授权的请求的回复, public
是隐含的设置。对于授权的请求的回复, private
选项是隐含的。他们可以通过在 Cache-Control
头部中指明相应的相反的选项以覆盖。
在理想情况下,任何内容都可以被尽可能缓存,而您的服务器只需要偶尔的提供一些验证内容即可。但这在现实中很少发生,因此您应该尝试设置一些明智的缓存策略,以在长期缓存和站点改变的需求间达到平衡。
在许多情况中,由于内容被产生的方式(如根据每个用户动态的产生)或者内容的特性(例如银行的敏感数据),这些内容不应该被缓存。另一些许多管理员在设置缓存时可能面对的问题是外部缓存的数据未过期,但新版本的数据已经产生。
这些都是经常遇到的问题,它们会影响缓存的性能和您提供的数据的准确性。然而,我们可以通过开发提前预见这些问题的缓存策略来缓解这些问题。
尽管您的实际情况会指导您选择的缓存策略,但是下面的建议能帮助您获得一些合理的决定。
在您担心使用哪一个特定的头部之前,有一些特定的步骤可以帮助您提高您的缓存命中率。一些建议如下:
对于不同的文件正确地选择不同的头部这件事,下面的内容可以作为一般性的参考:
Cache-Control
头部中使用 no-cache
或 no-store
选项。 ETag
和 Last-Modified
头部将允许缓存向原始服务器验证内容,并在内容未修改时刷新该内容新鲜度以减少负载。 关键之处便在于达到平衡,一方面可以尽量的进行缓存,另一方面为未来保留当改变发生时从而改变整个内容的机会。您的站点应该同时具有:
这样做的目的便是将内容尽可能的移动到第一个分类(尽量缓存)中的同时,维持可以接受的缓存命中率。
花时间确保您的站点使用了合适的缓存策略将对您的站点产生重要的影响。缓存使得您可以在保证服务同样内容的同时减少带宽的使用。您的服务器因此可以靠同样的硬件处理更多的流量。或许更重要的是,客户们能在您的网站中获得更快的体验,这会使得他们更愿意频繁的访问您的站点。尽管有效的Web缓存并不是银弹,但设置合适的缓存策略会使您以最小的代价获得可观的收获。
via: https://www.digitalocean.com/community/tutorials/web-caching-basics-terminology-http-headers-and-caching-strategies
作者: Justin Ellingwood 译者: wwy-hust 校对: wxy 推荐: royaso
本文由 LCTT 原创翻译,Linux中国 荣誉推出