透过浏览器看HTTP缓存(转)

透过浏览器看HTTP缓存

2016/01/17 · HTML5 ·
HTTP,
缓存

原文出处:
大额_skylar(@大额大额哼歌等日落)   

作为前端开发人员,对于我们的站点或应用的缓存机制我们能做的似乎不多,但这些却是与我们关注的性能息息相关的部分,站点没有做任何缓存机制,我们的页面可能会因为资源的下载和渲染变得很慢,但大家都知道去找前端去解决页面慢的问题而不会去找服务端的开发人员。因此,了解相关的缓存机制和充分的利用它似乎就变得必不可少。

web端的缓存机制其实有多种,我在这里只是学习和整理了以浏览器为载体的HTTP缓存机制,看看它是如何工作的。

文章目录:

  •   一、web缓存的种类
  •   二、为什么需要浏览器缓存?我们需要做些什么?
  •   三、使用Etag验证缓存的HTTP响应
  •   四、什么是Cache-Control?如何定义Cache-Control策略?
  •   五、已经缓存的响应,如何更新或废弃?
  •   六、对于缓存机制,现在可以做的有哪些?
  •         七、扩展阅读

 

 

一、概述

一、web缓存的种类

1.1 数据库缓存

我们可能听说过memcached,它就是一种数据库层面的缓存方案。数据库缓存是指,当web应用的关系比较复杂,数据库中的表很多的时候,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。

1.2 CDN缓存

CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。通常情况下,浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来说,浏览器和服务器之间的缓存机制,在这种架构下同样适用。

1.3 代理服务器缓存

代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。

1.4 浏览器缓存

每个浏览器都实现了 HTTP
缓存,我们通过浏览器使用HTTP协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作。

1.5 应用层缓存

应用层缓存是指我们在代码层面上做的缓存。通过代码逻辑,把曾经请求过的数据或资源等,缓存起来,再次需要数据时通过逻辑上的处理选择可用的缓存的数据。

作为前端开发人员,对于我们的站点或应用的缓存机制我们能做的似乎不多,但这些却是与我们关注的性能息息相关的部分,站点没有做任何缓存机制,我们的页面可能会因为资源的下载和渲染变得很慢,但大家都知道去找前端去解决页面慢的问题而不会去找服务端的开发人员。因此,了解相关的缓存机制和充分的利用它似乎就变得必不可少。
 

缓存通俗点,就是将已经得到的‘东东’存放在一个相对于自己而言,尽可能近的地方,以便下次需要时,不会再二笔地跑到起始点(很远的地方)去获取,而是就近解决,从而缩短时间和节约金钱(坐车要钱嘛)。Web缓存,也是同样的道理,说白了,就是当你第一次访问网址时,将这个东东(representations),如html页面、图片、JavaScript文件等,存在一个离你较近的地方,当你下次还需要它时,不用再一次跋山涉水到服务器(origin
servers)去获取。继而,web缓存的优势也就很明显了:

二、为什么需要浏览器缓存?我们需要做些什么?

我们知道通过HTTP协议,在客户端和浏览器建立连接时需要消耗时间,而大的响应需要在客户端和服务器之间进行多次往返通信才能获得完整的响应,这拖延了浏览器可以使用和处理内容的时间。这就增加了访问服务器的数据和资源的成本,因此利用浏览器的缓存机制重用以前获取的数据就变成了性能优化时需要考虑的事情。

那么有什么建议吗?当然。

为每个资源指定一个明确的缓存策略,用以定义资源是否可以缓存,由谁来缓存,可以缓存多久,并且在缓存时间到期时如何有效地重新验证。当服务器返回一个响应时,它需要在响应头中提供Cache-Control和ETag。

  说到浏览器中的缓存机制,其实就相当于HTTP协议定义的缓存机制,因为浏览器为我们实现了它。一般情况下我们会想到到HTTP响应头中的Expires,Cache-Control,Last-Modified.If-Modified-Since,Etag这样的与缓存相关的响应头信息。

  但是这里我们说服务器返回一个响应时提供必要的Cache-Control和Etag即可。这是为什么呢?

  因为Cache-Control与Expires的作用一致,Last-Modified与ETag的作用也相近。但它们有以下区别:

         
 图片 1

  现在默认浏览器均默认使用HTTP
1.1,所以Expires和Last-Modified的作用基本可以忽略,具备Cache-Control和Etag即可。

  当然用户的行为也会影响浏览器的缓存,像这样:

  图片 2

 

但我们先不考虑用户的操作的影响,来看看服务器提供Cache-Control和ETag响应头来进行的缓存是如何工作的。

web端的缓存机制其实有多种,我在这里只是学习和整理了以浏览器为载体的HTTP缓存机制,看看它是如何工作的。

  1、
减少了网络延迟,加快了页面响应速度,增强了用户体验嘛。(因为我是就近获取的,路程缩短了,所以响应速度当然比到遥远的服务器去获取快哦);

三、使用Etag验证缓存的HTTP响应

通常情况下,请求一个资源的过程大概是这样的:

图片 3

我在 再看Ajax 
中整理了HTTP请求的请求头和响应头的一些参数,这里就看下Etag的作用。

3.1 Etag的主要作用

服务器通过 ETag HTTP
头传递验证码,大概是像‘‘x123cef’’这样的字符串。当浏览器在资源过期后再次请求时,浏览器默认会通过If-None-Match传递Etag的验证码,通过验证码可以进行高效的资源更新检查:如果资源未更改,则不会传输任何数据。

Etag就主要用来在响应过期之后,验证资源是否被修改。

3.2 Etag的工作原理

如上图,服务器在第一次返回响应的时候设置了缓存的时间120s,假设浏览器在这120s经过之后再次请求服务器相同的资源,首先,浏览器会检查本地缓存并找到之前的响应,不幸的是,这个响应现在已经’过期’,无法在使用。此时,浏览器也可以直接发出新请求,获取新的完整响应,但是这样做效率较低,因为如果资源未被更改过,我们就没有理由再去下载与缓存中已有的完全相同的字节。

于是就到了Etag发挥作用的时候了,通常服务器生成并返回在Etag中的验证码,常常是文件内容的哈希值或者某个其他指纹码。客户端不必了解指纹码是如何生成的,只需要在下一个请求中将其发送给服务器(浏览器默认会添加):如果指纹码仍然一致,说明资源未被修改,服务器会反悔304
Not
Modified,这样我们就可以跳过下载,利用已经缓存了的资源,并且该资源会继续缓存120s。就像这样:

图片 4

文章目录:

  2、 减少了网络带宽消耗嘛。(就近获取);

四、什么是Cache-Control?如何定义Cache-Control?

服务器响应浏览器请求时响应头中的Cache-Control响应头使得每个资源都可以通过
Cache-Control HTTP 头来定义自己的缓存策略,Cache-Control
指令用来告诉我们,那个资源在什么条件下可以缓存,以及可以缓存多久。

4.1 Cache-Control头参数的含义(响应头中的Cache-Control)

1 no-cache :
表示必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌
(ETag),no-cache
会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。 2
no-store :
禁止缓存任何响应,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的响应。
3 public : 如果响应被标记为public,即使有关联的 HTTP
认证,甚至响应状态码无法正常缓存,响应也可以被缓存。 4 private :
浏览器可以缓存private响应,但是通常只为单个用户缓存,因此,不允许任何代理服务器对其进行缓存
。比如,用户浏览器可以缓存包含用户私人信息的 HTML 网页,但是 CDN
不能缓存。 5 max-age : 用来设置资源被缓存的最长时间(单位是秒)。

1
2
3
4
5
6
7
8
9
1 no-cache : 表示必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。
 
2 no-store : 禁止缓存任何响应,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的响应。
 
3 public : 如果响应被标记为public,即使有关联的 HTTP 认证,甚至响应状态码无法正常缓存,响应也可以被缓存。
 
4 private : 浏览器可以缓存private响应,但是通常只为单个用户缓存,因此,不允许任何代理服务器对其进行缓存 。比如,用户浏览器可以缓存包含用户私人信息的 HTML 网页,但是 CDN 不能缓存。
 
5 max-age :  用来设置资源被缓存的最长时间(单位是秒)。

 

4.2 如何使用Cache-Control

通常,我们可以通过下图的流程来设置合适的响应头的Cache-Control头。

图片 5

 

  •   一、web缓存的种类
  •   二、为什么需要浏览器缓存?我们需要做些什么?
  •   三、使用Etag验证缓存的HTTP响应
  •   四、什么是Cache-Control?如何定义Cache-Control策略?
  •   五、已经缓存的响应,如何更新或废弃?
  •   六、对于缓存机制,现在可以做的有哪些?
  •         七、扩展阅读

  3、 通过缓存,我们都不用到服务器 (origin
servers)去请求了,从而也就相应地减轻了服务器的压力。

五、已经缓存的响应,如何更新或废弃?

一般情况下,浏览器发出的所有 HTTP
请求会首先被路由到浏览器的缓存,以查看是否缓存了可以用于实现请求的有效响应。如果有匹配的响应,会直接从缓存中读取响应,这样就避免了网络延迟以及传输产生的数据成本。然而,如果我们希望更新或废弃已缓存的响应,该怎么办?

假设我们已经告诉访问者某个 CSS 样式表缓存长达 24 小时
(max-age=86400),但是设计人员刚刚提交了一个更新,我们希望所有用户都能使用。我们该如何通知所有访问者缓存的
CSS 副本已过时,需要更新缓存?

实际上以前没有请求过该资源的新的用户会得到更新的资源,但是请求过资源的用户将在过期时间达到之前一直得到旧的被缓存的资源,直到他手动的去清理了浏览器的缓存。手动清理浏览器缓存这种事可能只有程序员才会做,那么我们要怎么做才能让用户得到更新后的资源呢?

其实很简单,我们可以在资源的内容更改后,更改资源的网址,强制用户下载新响应。比如在资源链接后添加参数:

图片 6

 

那web缓存将这些东东放在哪儿呢?下面我就看看有哪些缓存种类,从而了解放在哪吧。

六、对于缓存机制,现在可以做的有哪些?

我在浏览资料的时候发现了一个caching
checklist,比较具有参考价值,我们可以遵循建议合理的利用缓存机制:

1
使用一致的网址:如果在不同的网址上提供相同的内容,那么将会多次获取和存储相同的内容。提示:网址是区分大小写的!2
确保服务器提供验证码
(ETag):通过验证码,如果服务器上的资源未被更改,就不必传输相同的字节。3
确定代理缓存可以缓存哪些资源:对所有用户的响应完全相同的资源很适合由 CDN
或其他代理缓存进行缓存。4
确定每个资源的最优缓存周期:不同的资源可能有不同的更新要求。审查并确定每个资源适合的
max-age。5 确定网站的最佳缓存层级:对 HTML
文档组合使用包含内容指纹码的资源网址以及短时间或 no-cache
的生命周期,可以控制客户端获取更新的速度。6
变动最小化:有些资源的更新比其他资源频繁。如果资源的特定部分(例如
JavaScript 函数或一组 CSS
样式)会经常更新,应考虑将其代码作为单独的文件提供。这样,每次获取更新时,剩余内容(例如不会频繁更新的库代码)可以从缓存中获取,确保下载的内容量最少。

1
1 使用一致的网址:如果在不同的网址上提供相同的内容,那么将会多次获取和存储相同的内容。提示:网址是区分大小写的!2 确保服务器提供验证码 (ETag):通过验证码,如果服务器上的资源未被更改,就不必传输相同的字节。3 确定代理缓存可以缓存哪些资源:对所有用户的响应完全相同的资源很适合由 CDN 或其他代理缓存进行缓存。4 确定每个资源的最优缓存周期:不同的资源可能有不同的更新要求。审查并确定每个资源适合的 max-age。5 确定网站的最佳缓存层级:对 HTML 文档组合使用包含内容指纹码的资源网址以及短时间或 no-cache 的生命周期,可以控制客户端获取更新的速度。6 变动最小化:有些资源的更新比其他资源频繁。如果资源的特定部分(例如 JavaScript 函数或一组 CSS 样式)会经常更新,应考虑将其代码作为单独的文件提供。这样,每次获取更新时,剩余内容(例如不会频繁更新的库代码)可以从缓存中获取,确保下载的内容量最少。

 

一、web缓存的种类

1.1 数据库缓存

  我们可能听说过memcached,它就是一种数据库层面的缓存方案。数据库缓存是指,当web应用的关系比较复杂,数据库中的表很多的时候,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。

1.2 CDN缓存

  CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。通常情况下,浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来说,浏览器和服务器之间的缓存机制,在这种架构下同样适用。

1.3 代理服务器缓存

  代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。

1.4 浏览器缓存

  每个浏览器都实现了 HTTP
缓存,我们通过浏览器使用HTTP协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作。

1.5 应用层缓存

  应用层缓存是指我们在代码层面上做的缓存。通过代码逻辑,把曾经请求过的数据或资源等,缓存起来,再次需要数据时通过逻辑上的处理选择可用的缓存的数据。

二、Web缓存的种类

七、扩展阅读

[web缓存机制系列]

[Google Developer Browser
Caching]

[HTTP
Caching]

[Caching Tutorial]

[HTTP Caching FAQ
MDN]

[浏览器缓存机制]

1 赞 11 收藏
评论

图片 7

二、为什么需要浏览器缓存?我们需要做些什么?

   我们知道通过HTTP协议,在客户端和浏览器建立连接时需要消耗时间,而大的响应需要在客户端和服务器之间进行多次往返通信才能获得完整的响应,这拖延了浏览器可以使用和处理内容的时间。这就增加了访问服务器的数据和资源的成本,因此利用浏览器的缓存机制重用以前获取的数据就变成了性能优化时需要考虑的事情。

  那么有什么建议吗?当然。

  为每个资源指定一个明确的缓存策略,用以定义资源是否可以缓存,由谁来缓存,可以缓存多久,并且在缓存时间到期时如何有效地重新验证。当服务器返回一个响应时,它需要在响应头中提供Cache-Control和ETag。

  说到浏览器中的缓存机制,其实就相当于HTTP协议定义的缓存机制,因为浏览器为我们实现了它。一般情况下我们会想到到HTTP响应头中的Expires,Cache-Control,Last-Modified.If-Modified-Since,Etag这样的与缓存相关的响应头信息。

  但是这里我们说服务器返回一个响应时提供必要的Cache-Control和Etag即可。这是为什么呢?

  因为Cache-Control与Expires的作用一致,Last-Modified与ETag的作用也相近。但它们有以下区别:

         
 图片 8

  现在默认浏览器均默认使用HTTP 1.1,所以Expires和Last-Modified的作用基本可以忽略,具备Cache-Control和Etag即可。

  当然用户的行为也会影响浏览器的缓存,像这样:

  图片 9

 

  但我们先不考虑用户的操作的影响,来看看服务器提供Cache-Control和ETag响应头来进行的缓存是如何工作的。  

–数据库缓存–:

三、使用Etag验证缓存的HTTP响应

   通常情况下,请求一个资源的过程大概是这样的:

      图片 10

  我在 再看Ajax 
中整理了HTTP请求的请求头和响应头的一些参数,这里就看下Etag的作用。

3.1 Etag的主要作用

  服务器通过 ETag HTTP
头传递验证码,大概是像‘‘x123cef’’这样的字符串。当浏览器在资源过期后再次请求时,浏览器默认会通过If-None-Match传递Etag的验证码,通过验证码可以进行高效的资源更新检查:如果资源未更改,则不会传输任何数据。

  Etag就主要用来在响应过期之后,验证资源是否被修改。

3.2 Etag的工作原理

  如上图,服务器在第一次返回响应的时候设置了缓存的时间120s,假设浏览器在这120s经过之后再次请求服务器相同的资源,首先,浏览器会检查本地缓存并找到之前的响应,不幸的是,这个响应现在已经’过期’,无法在使用。此时,浏览器也可以直接发出新请求,获取新的完整响应,但是这样做效率较低,因为如果资源未被更改过,我们就没有理由再去下载与缓存中已有的完全相同的字节。

  于是就到了Etag发挥作用的时候了,通常服务器生成并返回在Etag中的验证码,常常是文件内容的哈希值或者某个其他指纹码。客户端不必了解指纹码是如何生成的,只需要在下一个请求中将其发送给服务器(浏览器默认会添加):如果指纹码仍然一致,说明资源未被修改,服务器会反悔304
Not
Modified,这样我们就可以跳过下载,利用已经缓存了的资源,并且该资源会继续缓存120s。就像这样:

  图片 11  

当web应用关系复杂,数据表蹭蹭蹭往上涨时,可以将查询后的数据放到内存中进行缓存,下次再查询时,就直接从内存缓存中获取,从而提高响应速度。

四、什么是Cache-Control?如何定义Cache-Control?

  服务器响应浏览器请求时响应头中的Cache-Control响应头使得每个资源都可以通过
Cache-Control HTTP 头来定义自己的缓存策略,Cache-Control
指令用来告诉我们,那个资源在什么条件下可以缓存,以及可以缓存多久。

4.1 Cache-Control头参数的含义(响应头中的Cache-Control)

  

图片 12😉

1 no-cache : 表示必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。

2 no-store : 禁止缓存任何响应,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的响应。

3 public : 如果响应被标记为public,即使有关联的 HTTP 认证,甚至响应状态码无法正常缓存,响应也可以被缓存。

4 private : 浏览器可以缓存private响应,但是通常只为单个用户缓存,因此,不允许任何代理服务器对其进行缓存 。比如,用户浏览器可以缓存包含用户私人信息的 HTML 网页,但是 CDN 不能缓存。

5 max-age :  用来设置资源被缓存的最长时间(单位是秒)。

图片 13😉

 

4.2 如何使用Cache-Control

  通常,我们可以通过下图的流程来设置合适的响应头的Cache-Control头。

  图片 14

 

–CDN缓存–:

五、已经缓存的响应,如何更新或废弃?

   一般情况下,浏览器发出的所有 HTTP
请求会首先被路由到浏览器的缓存,以查看是否缓存了可以用于实现请求的有效响应。如果有匹配的响应,会直接从缓存中读取响应,这样就避免了网络延迟以及传输产生的数据成本。然而,如果我们希望更新或废弃已缓存的响应,该怎么办?

  假设我们已经告诉访问者某个 CSS 样式表缓存长达 24 小时
(max-age=86400),但是设计人员刚刚提交了一个更新,我们希望所有用户都能使用。我们该如何通知所有访问者缓存的
CSS 副本已过时,需要更新缓存? 

  实际上以前没有请求过该资源的新的用户会得到更新的资源,但是请求过资源的用户将在过期时间达到之前一直得到旧的被缓存的资源,直到他手动的去清理了浏览器的缓存。手动清理浏览器缓存这种事可能只有程序员才会做,那么我们要怎么做才能让用户得到更新后的资源呢?

  其实很简单,我们可以在资源的内容更改后,更改资源的网址,强制用户下载新响应。比如在资源链接后添加参数:

  图片 15

CDN通俗点,就是当我们发送一个web请求时,会先经过它一道手,然后它帮我们计算路径,去哪得到这些东东(representations)的路径短且快。这个是网站管理员部署的,所以他们也可以将大家经常访问的representations放在CDN里,这样,就响应就更快了。

六、对于缓存机制,现在可以做的有哪些?

   我在浏览资料的时候发现了一个caching
checklist,比较具有参考价值,我们可以遵循建议合理的利用缓存机制:

图片 16😉

1 使用一致的网址:如果在不同的网址上提供相同的内容,那么将会多次获取和存储相同的内容。提示:网址是区分大小写的!

2 确保服务器提供验证码 (ETag):通过验证码,如果服务器上的资源未被更改,就不必传输相同的字节。

3 确定代理缓存可以缓存哪些资源:对所有用户的响应完全相同的资源很适合由 CDN 或其他代理缓存进行缓存。

4 确定每个资源的最优缓存周期:不同的资源可能有不同的更新要求。审查并确定每个资源适合的 max-age。

5 确定网站的最佳缓存层级:对 HTML 文档组合使用包含内容指纹码的资源网址以及短时间或 no-cache 的生命周期,可以控制客户端获取更新的速度。

6 变动最小化:有些资源的更新比其他资源频繁。如果资源的特定部分(例如 JavaScript 函数或一组 CSS 样式)会经常更新,应考虑将其代码作为单独的文件提供。这样,每次获取更新时,剩余内容(例如不会频繁更新的库代码)可以从缓存中获取,确保下载的内容量最少。

图片 17😉

 

–代理服务器缓存–:

七、扩展阅读

[web缓存机制系列]

[Google Developer Browser
Caching]

[HTTP
Caching]

[Caching Tutorial]

[HTTP Caching FAQ
MDN]

[浏览器缓存机制]

 

代理服务器缓存,其实跟下面即将讲的浏览器缓存性质差不多,差别就是代理服务器缓存面向的群体更广,规模更大而已。即,它不只为一个用户服务,一般为大量用户提供服务,同一个副本会被重用多次,因此在减少相应时间和带宽使用方面很有效。

–浏览器缓存–:

简而言之,就是,每个浏览器都实现了 HTTP
缓存,我们通过浏览器使用HTTP协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作。当我们点击浏览器上‘后退’或者‘前进’按钮时,显得特别有用。

三、Web缓存的执行机制

所谓机制就是一些双方的约定,清晰地告诉对方,什么时候该做什么事。web缓存也一样,你总得告诉我(请求)什么时候到缓存中去获取,什么到服务器去获取representations吧。So,也得有一套相应的机制,web
缓存机制分为两大部分http协议(HTTP1.0和HTTP1.1)和网站管理人员制定的协议。抛开网站内部制定的协议,我们来看看http协议中定义的缓存机制。

By the
way,我们可以在HTML文档中的<head>中通过<meta>来缓存,如下:

<meta http-equiv="Pragma" content="no-cache"/>

但,它只有部分浏览器可以用,并且代理服务器也不会鸟它。(因为meta在html中,代理服务器几乎不回去读它滴)。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website