Web缓存基础:术语、HTTP报头和缓存策略

简介

对于您的站点的访问者来讲,智能化的内容缓存是提升用户体验最有效的方式之一。缓存,或者对以前的请求的临时存储,是HTTP协议实现中最核心的内容分发策略之一。分发路径中的组件都可以缓存内容来加速后续的请求,这受控于对该内容所声明的缓存策略。后端

在这份指南中,咱们将讨论一些Web内容缓存的基本概念。这主要包括如何选择缓存策略以保证互联网范围内的缓存可以正确的处理您的内容。咱们将谈一谈缓存带来的好处、反作用以及不一样的策略能带来的性能和灵活性的最大结合。浏览器

什么是缓存(caching)?

缓存(caching)是一个描述存储可重用资源以便加快后续请求的行为的术语。有许多不一样类型的缓存,每种都有其自身的特色,应用程序缓存和内存缓存因为其对特定回复的加速,都很经常使用。缓存

这份指南的主要讲述的Web缓存是一种不一样类型的缓存。Web缓存是HTTP协议的一个核心特性,它能最小化网络流量,而且提高用户所感知的整个系统响应速度。内容从服务器到浏览器的传输过程当中,每一个层面均可以找到缓存的身影。服务器

Web缓存根据特定的规则缓存相应HTTP请求的响应。对于缓存内容的后续请求即可以直接由缓存知足而不是从新发送请求到Web服务器。cookie

好处

有效的缓存技术不只能够帮助用户,还能够帮助内容的提供者。缓存对内容分发带来的好处有:网络

  • 减小网络开销:内容能够在从内容提供者到内容消费者网络路径之间的许多不一样的地方被缓存。当内容在距离内容消费者更近的地方被缓存时,因为缓存的存在,请求将不会消耗额外的网络资源。
  • 加快响应速度:因为并非必须经过整个网络往返,缓存可使内容的得到变得更快。缓存放在距用户更近的地方,例如浏览器缓存,使得内容的获取几乎是瞬时的。
  • 在一样的硬件上提升速度:对于保存原始内容的服务器来讲,更多的性能能够经过容许激进的缓存策略从硬件上压榨出来。内容拥有者们能够利用分发路径上某个强大的服务器来应对特定内容负载的冲击。
  • 网络中断时内容依旧可用:使用某种策略,缓存能够保证在原始服务器变得不可用时,相应的内容对用户依旧可用。

术语

在面对缓存时,您可能对一些常常遇到的术语可能不太熟悉。一些常见的术语以下:架构

  • 原始服务器:原始服务器是内容的原始存放地点。若是您是Web服务器管理员,它就是您所管理的机器。它负责为任何不能从缓存中获得的内容进行回复,而且负责设置全部内容的缓存策略。
  • 缓存命中率:一个缓存的有效性依照缓存的命中率进行度量。它是能够从缓存中获得数据的请求数与全部请求数的比率。缓存命中率高意味着有很高比例的数据能够从缓存中得到。这一般是大多数管理员想要的结果。
  • 新鲜度:新鲜度用来描述一个缓存中的项目是否依旧适合返回给客户端。缓存中的内容只有在由缓存策略指定的新鲜期内才会被返回。
  • 过时内容:缓存中根据缓存策略的新鲜期设置已过时的内容。过时的内容被标记为“陈旧”。一般,过时内容不能用于回复客户端的请求。必须从新从原始服务器请求新的内容或者至少验证缓存的内容是否仍然准确。
  • 校验:缓存中的过时内容能够验证是否有效以便刷新过时时间。验证过程包括联系原始服务器以检查缓存的数据是否依旧表明了最近的版本。
  • 失效:失效是依据过时日期从缓存中移除内容的过程。当内容在原始服务器上已被改变时就必须这样作,缓存中过时的内容会致使客户端发生问题。

还有许多其余的缓存术语,不过上面的这些应该能帮助您开始。并发

什么能被缓存?

某些特定的内容比其余内容更容易被缓存。对大多数站点来讲,一些适合缓存的内容以下:工具

  • Logo和商标图像
  • 普通的不变化的图像(例如,导航图标)
  • CSS样式表
  • 普通的Javascript文件
  • 可下载的内容
  • 媒体文件

这些文件更倾向于不常常改变,因此长时间的对它们进行缓存能得到好处。性能

一些项目在缓存中必须加以注意:

  • HTML页面
  • 会替换改变的图像
  • 常常修改的Javascript和CSS文件
  • 须要有认证后的cookies才能访问的内容

一些内容历来不该该被缓存:

  • 与敏感信息相关的资源(银行数据,等)
  • 用户相关且常常更改的数据

除上面的通用规则外,一般您须要指定一些规则以便于更好地缓存不一样种类的内容。例如,若是登陆的用户都看到的是一样的网站视图,就应该在任何地方缓存这个页面。若是登陆的用户会在一段时间内看到站点中用户特定的视图,您应该让用户的浏览器缓存该数据而不该让任何中介节点缓存该视图。

Web内容缓存的位置

Web内容会在整个分发路径中的许多不一样的位置被缓存:

  • 浏览器缓存:Web浏览器自身会维护一个小型缓存。典型地,浏览器使用一种策略指示缓存最重要的内容。这多是用户相关的内容或可能会再次请求且下载代价较高。
  • 中间缓存代理:任何在客户端和您的基础架构之间的服务器均可以定期望缓存一些内容。这些缓存可能由ISP(网络服务提供者)或者其余独立组织提供。
  • 反向缓存:您的服务器基础架构能够为后端的服务实现本身的缓存。若是实现了缓存,那么即可以在处理请求的位置返回相应的内容而不用每次请求都使用后端服务。

上面的这些位置一般均可以根据它们自身的缓存策略和内容源的缓存策略缓存一些相应的内容。

缓存头部

缓存策略依赖于两个不一样的因素。所缓存的实体自己须要决定是否应该缓存可接受的内容。它能够只缓存部分能够缓存的内容,但不能缓存超过限制的内容。

缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。这些策略主要经过特定的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头部的隐语

Vary头部提供给您存储同一个内容的不一样版本的能力,代价是下降了缓存的容量。

在使用Accept-Encoding时,设置Vary头部容许明确区分压缩和未压缩的内容。这在服务某些不能处理压缩数据的浏览器时很重要,它能够保证基本的可用性。Vary的一个典型的值是Accept-Encoding,它只有两到三个可选的值。

一开始看上去User-Agent这样的头部能够用于区分移动浏览器和桌面浏览器,以便您的站点提供差别化的服务。但User-Agent字符串是非标准的,结果将会形成在中间缓存中保存同一内容的许多不一样版本的缓存,这会致使缓存命中率的下降。Vary头部应该谨慎使用,尤为是您不具有在您控制的中间缓存中使请求标准化的能力(也许能够,好比您能够控制CDN的话)。

缓存控制标志怎样影响缓存

上面咱们提到了Cache-Control头部如何被用与现代缓存策略标准。可以经过这个头部设定许多不一样的缓存指令,多个不一样的指令经过逗号分隔。

一些您可使用的指示内容缓存策略的Cache-Control的选项以下:

  • no-cache:这个指令指示全部缓存的内容在新的请求到达时必须先从新验证,再发送给客户端。这条指令实际将内容马上标记为过时的,但容许经过验证手段从新验证以免从新下载整个内容。
  • no-store:这条指令指示缓存的内容不能以任何方式被缓存。它适合在回复敏感信息时设置。
  • public:它将内容标记为公有的,这意味着它能被浏览器和其余任何中间节点缓存。一般,对于使用了HTTP验证的请求,其回复被默认标记为privatepublic标记将会覆盖这个设置。
  • private:它将内容标记为私有的。私有数据能够被用户的浏览器缓存,但不能被任何中间节点缓存。它一般用于用户相关的数据。
  • max-age:这个设置指示了缓存内容的最大生存期,它在最大生存期后必须在源服务器处被验证或被从新下载。在现代浏览器中这个选项大致上取代了Expires头部,浏览器也将其做为决定内容的新鲜度的基础。这个选项的值以秒为单位表示,最大能够表示一年的新鲜期(31536000秒)。
  • s-maxage:这个选项很是相似于max-age,它指明了内容可以被缓存的时间。区别是这个选项只在中间节点的缓存中有效。结合这两个选项能够构建更加灵活的缓存策略。
  • must-revalidate:它指明了由max-ages-maxageExpires头部指明的新鲜度信息必须被严格的遵照。它避免了缓存的数据在网络中断等相似的场景中被使用。
  • proxy-revalidate:它和上面的选项有着同样的做用,但只应用于中间的代理节点。在这种状况下,用户的浏览器能够在网络中断时使用过时内容,但中间缓存内容不能用于此目的。
  • no-transform:这个选项告诉缓存在任何状况下都不能由于性能的缘由修改接收到的内容。这意味着,缓存不容许压缩接收到的内容(没有从原始服务器处接收过压缩版本的该内容)并发送。

这些选项可以以不一样的方式结合以得到不一样的缓存行为。一些互斥的值以下:

  • no-cacheno-store以及由其余前面未提到的选项指明的经常使用的缓存行为
  • publicprivate

若是no-storeno-cache都被设置,那么no-store会取代no-cache。对于非受权的请求的回复,public是隐含的设置。对于受权的请求的回复,private选项是隐含的。他们能够经过在Cache-Control头部中指明相应的相反的选项以覆盖。

开发一种缓存策略

在理想状况下,任何内容均可以被尽量缓存,而您的服务器只须要偶尔的提供一些验证内容便可。但这在现实中不多发生,所以您应该尝试设置一些明智的缓存策略,以在长期缓存和站点改变的需求间达到平衡。

常见问题

在许多状况中,因为内容被产生的方式(如根据每一个用户动态的产生)或者内容的特性(例如银行的敏感数据),这些内容不该该被缓存。另外一些许多管理员在设置缓存时可能面对的问题是外部缓存的数据未过时,但新版本的数据已经产生。

这些都是常常遇到的问题,它们会影响缓存的性能和您提供的数据的准确性。然而,咱们能够经过开发提早预见这些问题的缓存策略来缓解这些问题。

通常性建议

尽管您的实际状况会指导您选择的缓存策略,可是下面的建议能帮助您得到一些合理的决定。

在您担忧使用哪个特定的头部以前,有一些特定的步骤能够帮助您提升您的缓存命中率。一些建议以下:

  • 为图像、CSS和共享的内容创建特定的文件夹:将内容放到特定的文件夹内使得您能够方便的从您的站点中的任何页面引用这些内容。
  • 使用一样的URL来表示一样的内容:因为缓存使用内容请求中的主机名和路径做为键,所以应保证您的全部页面中的该内容的引用方式相同,前一个建议能让这点更加容易作到。
  • 尽量使用CSS图像拼接:对于像图标和导航等内容,使用CSS图像拼接可以减小渲染您页面所须要的请求往返,而且容许对拼接缓存很长一段时间。
  • 尽量将主机脚本和外部资源本地化:若是您使用Javascript脚本和其余外部资源,若是上游没有提供合适的缓存头部,那么您应考虑将这些内容放在您本身的服务器上。您应该注意上游的任何更新,以便更新本地的拷贝。
  • 对缓存内容收集文件摘要:静态的内容好比CSS和Javascript文件等一般比较适合收集文件摘要。这意味着为文件名增长一个独特的标志符(一般是这个文件的哈希值)能够在文件修改后绕开缓存保证新的内容被从新获取。有不少工具能够帮助您建立文件摘要而且修改HTML文档中的引用。

对于不一样的文件正确地选择不一样的头部这件事,下面的内容能够做为通常性的参考:

  • 容许全部的缓存存储通常内容:静态内容以及非用户相关的内容应该在分发链的全部节点被缓存。这使得中间节点能够将该内容回复给多个用户。
  • 容许浏览器缓存用户相关的内容:对于每一个用户的数据,一般在用户本身的浏览器中缓存是能够被接受且有益的。缓存在用户自身的浏览器可以使得用户在接下来的浏览中可以瞬时读取,但这些内容不适合在任何中间代理节点缓存。
  • 将时间敏感的内容做为特例:若是您的数据是时间敏感的,那么相对上面两条参考,应该将这些数据做为特例,以保证过时的数据不会在关键的状况下被使用。例如,您的站点有一个购物车,它应该马上反应购物车里面的物品。依据内容的特色,能够在Cache-Control头部中使用no-cacheno-store选项。
  • 老是提供验证器:验证器使得过时的内容能够无需从新下载而获得刷新。设置ETagLast-Modified头部将容许缓存向原始服务器验证内容,并在内容未修改时刷新该内容新鲜度以减小负载。
  • 对于支持的内容设置长的新鲜期:为了更加有效的利用缓存,一些做为支持性的内容应该被设置较长的新鲜期。这一般比较适合图像和CSS等由用户请求用来渲染HTML页面的内容。和文件摘要一块儿,设置延长的新鲜期将容许缓存长时间的存储这些资源。若是资源发生改变,修改的文件摘要将会使缓存的数据无效并触发对新的内容的下载。那时,新的支持的内容会继续被缓存。
  • 对父内容设置短的新鲜期:为了使得前面的模式正常工做,容器类的内容应该相应的设置短的新鲜期,或者设置不所有缓存。这一般是在其余协助内容中使用的HTML页面。这个HTML页面将会被频繁的下载,使得它能快速的响应改变。支持性的内容所以能够被尽可能缓存。

关键之处便在于达到平衡,一方面能够尽可能的进行缓存,另外一方面为将来保留当改变发生时从而改变整个内容的机会。您的站点应该同时具备:

  • 尽可能缓存的内容
  • 拥有短的新鲜期的缓存内容,能够被从新验证
  • 彻底不被缓存的内容

这样作的目的即是将内容尽量的移动到第一个分类(尽可能缓存)中的同时,维持能够接受的缓存命中率。

相关文章
相关标签/搜索