HTTP缓存笔记

Author Avatar
高翔 2月 25, 2017

网上笔记的摘抄,加上自己的理解

HTTP缓存

使用缓存有如下几个好处:

  • 缓存减少了冗余的数据传输, 节省了你的网络费用。 (将每次传送的相同的直接缓存起来)
  • 缓存缓解了网络瓶颈的问题。 不需要更多的带宽就能够更快地加载页面。 (这是当然)
  • 缓存降低了对原始服务器的要求。 服务器可以更快地响应,避免过载的出现。
  • 缓存降低了距离时延, 因为从较远的地方加载页面会更慢一些。

缓存分类

  1)私有缓存
  常见就是我们的浏览器里内置的缓存。

  2)公有缓存
  常见的就是代理缓存,不多介绍。   

3.缓存的处理流程

image

  处理流程图,如上所示,下面分步骤具体介绍:

1)请求处理

  用户发起一个http请求,缓存获取到URL,根据URL查找是否有匹配的副本,这个副本可能在内存中,也可能在本地磁盘。

2) 新鲜度检测

  如果缓存中存在所请求资源的副本,则进行新鲜度检测。HTTP发起一个请求时,发现缓存中有相应的副本,接着就会检查这个副本有没有过期,如果没有过期,直接使用。如果已经过期,则进行再验证。具体的实现在下面会介绍。

3)服务器再验证

  缓存中的文档过期了并不代表他和服务器上的不一样,所以这个时候就需要问问服务器,过期的这段时间里这个文档到底有没有改变。如果改变了,缓存就会获取一份新的文档副本,然后发送给客户端。如果没有改变,缓存只需要获取新的首部,包括一个新的过期时间,并对缓存中的首部更新。

  4)创建响应并返回

  我们希望缓存看起来就像是来自原始服务器一样,缓存将已缓存的服务器响应首部作为响应首部,发送给客户端。

  4.保质期的实现

  HTTP中,通过Cache-Control首部和Expires首部为文档指定了过期时间,通过对过期时间的判断,缓存就可以知道文档是不是在保质期内。Expires首部和Cache-Control:max-age首部都是来告诉缓存文档有没有过期,
  HTTP 1.1为了修正这个问题,引入了Cache-Control:max-age首部,这个首部使用相对时间来控制保质期,让一切变得更加合理。

  5.服务器再验证的实现

  缓存要问问服务器。HTTP中,使用两个请求请首部来完成这个功能:If-Modified-Sice和If-None-Match。为啥又要两个首部来完成这个功能了?答案还是因为历史的原因。一开始使用 If-Modified-Sice:首部,date是上一次缓存牛奶时,响应中Last-Modified首部的值。
  客户端拿着这个值,问服务器,这段时间内这个牛奶你有没有修改过?服务器看了看这个牛奶的修改时间,如果没有修改过,会返回一个304 Not Modified的响应;如果修改过,把最新的牛奶返回给客户端。后来,人们发现这样有问题,因为就算修改时间变化了,文档也不一定发生改变!于是乎,就有了 If-None-Match:首部,tag是上一次缓存文档时,响应中Etag的值,Etag是一种唯一标识资源的方式,就像java中的hashcode,如果hashcode不一样,那么两个对象肯定不一样!

  6.试探性过期

  如果响应中既没有Cache-Control:max-age首部又没有Expires首部,缓存可以计算出一个试探性最大使用期。这东西打个比方就是缓存会根据响应的Last-Modified来决定这文档靠不靠谱,需不需要再验证,如果Last-Modified中的日期是很早之前,那缓存就认为这文档挺靠谱,近期之内应该不会变化;如果Last-Modified中的日期是最近几天,那缓存可能就认为这文档可能经常改变,不靠谱。当然这么粗略的判断想想就知道不严谨,所以我们一定要设置Expires首部和Cache-Control首部。

  • Expires:绝对过期时间,优先级低,快被淘汰了,因为根据服务器的时间会有差异
  • Cache-Control:相对过期时间
  • Last-Modified:最后更改时间,但是有些周期性更新,实际资源没有更改,所有引入Etag
  • Etag:标识版本,如果资源没有变化,就不会改变版本

      7.返回状态码说明

    image