HTTP缓存机制

HTTP缓存是web开发中经常碰到的问题,但是之前虽然看过,那时候web开发刚开始做,概念有点儿模糊不清,所以重读了《HTTP权威指南》的缓存部分。这里对自己的理解做一下记录。

为什么要缓存

为什么要做缓存?如果你看到了这篇文章,其实心中肯定有了一个作缓存的需求和目标。缓存的目的无非就是提高用户体验,节省资源两方面。

  • 提高用户体验:
    从提高用户体验来讲,就是用户能够看到反馈的时间越短越好,速度越快越好。那么如何才能提高速度呢?当然是数据和用户越近越好,最好就在本地;还有就是网速越快越好,最好连接网络就能访问。我们都知道本地应用是最快的,因为所有的都在你的电脑里了,不需要再费劲去网上下载了。缓存的目的就是为了尽量完成这个工作而设计的。
  • 节省资源:
    这个怎么说呢,如果你要访问一个网站,第一次你肯定没有这些数据,但是如果访问后所有的数据都保存在了本地,或者离你很近的地方,就省得在网络的海洋漫游过来了,这当然就节省了不少流量,当然你的计费方式是按带宽来的,多少流量无所谓,可是对于提供网站服务的供应商来说这些都是白花花的银子啊,能剩就剩,节约每一个铜板嘛。

    缓存的机制

    这里只介绍基于HTTP协议的缓存。也许做web开发的都听过expires,cache-control,If-Modified-Since等缓存控制的HTTP头,这些眼花缭乱的头真让让人头晕啊,到底他们之间是什么关系,写了那么多,但是缓存是不是生效了?怎么生效的啊?带着这些疑问我也仔细阅读了一下书里的内容。其实一幅图可以说明很多问题:

通过这个流程图我们可以看出有三个方向:

  1. 未找到缓存(黑色线)
    当没有找到缓存时,说明我们本地并没有这些数据,这种情况一般发生在我们首次访问网站,或者以前访问过,但是清除过缓存后。这时浏览器没有这些数据,浏览器就会先访问服务器,然后把服务器上的内容取回来,内容取回来以后,就要根据情况来决定是否要保留到缓存中了。这个地方与cache-control字段的内容有关系。
  2. 缓存未过期(蓝色线)
    缓存未过期,指的是本地缓存没有过期,不需要访问服务器了,直接就可以拿本地的缓存作为响应在本地使用了。这样节省了不少网络成本,提高了用户体验过。这个内容跟expires字段和cache-control有密切的联系。
  3. 缓存已过期(红色线)
    缓存过期,是根据expirescache-control来判断的,当满足过期的条件时,会向服务器发送请求,发送的请求一般都会进行一个验证,目的是虽然缓存文档过期了,但是文档内容不一定会有什么改变,所以服务器返回的也许是一个新的文档,这时候的HTTP状态码是200,或者返回的只是一个最新的时间戳和304状态码。

下面就针对这些情况和其对应的字段及字段的优先级进行性说明:
第一优先级cache-control(expires)。下面的表是从高到低的顺序优先级递减。

字段 备注
Cache-Control no-store 不存储缓存数据,禁止对相应进行复制
Cache-Control no-cache 可以存储在本地缓存区中,但是必须进行新鲜度再验证满足之后才能使用
Pragma no-cache 用在HTTP/1.0协议中,与Cache-control一样
Cache-Control must-revalidate 表示必须进行新鲜度的再验证之后才能使用,与no-cache的区别是,这个是在过期之后才会进行强制校验,一般用在没有使用cache-control等字段明确规定的缓存时,这时会自动使用缓存策略,如果不想自动缓存,则使用这个字段值(实际测试跟no-cache没什么区别)
Cache-Control max-age 相对存活时间,相对与Last-Modified的时间,如果当前时间与Last时间只差小于这个值,则不用访问服务器,直接使用缓存,否者要进行新鲜度校验
Expires date 旧版本的使用方式,date是具体的过期时间,当没有cacche-control时使用

上面这些主要是在本地进行的,主要作用就是决定用本地缓存还是用远程服务器的资源。下面有要介绍的是新鲜度校验阶段要用到的HTTP控制字段。

字段 备注
If-Modified-Science date 初始值与Last-Modified的值一样,当请求服务器时判断文件的Last-Modified,如果比现在的时间晚,证明做过修改,需要冲重新请求文档,返回的Last-Modified为最新的时间,下次次请求时,If-Modified-Science的值会更新到与Last-Modified一致,然后在发送请求.如果时间与现在的一样,证明那个没有更新,直接返回304状态码
Last-Modified date 表示的就是文档在服务器上的最后更新时间
If-None-Match 版本号 前面的If-Modified-Science有一个缺点就是虽然文件的更新时间变了,但是内容并没有改变,也会重新发送文档,为了减少网络传输,这里就需要If-None-Match来判断了。主要是判断版本号与当前etag不一致时,更新文档,当Etag一致时只需更新文件更新时间就可以了
Etag 版本号 标识当前文档内容

优先级: Etag > Last-Modified 也就是说如果有Etag,就用If-None-Match来验证,否者才能用If-Modified-Science验证.

基本上常用的HTTP缓存功能就是这些。下面介绍一下在Nginx服务器先如何配置及前端页面如何访问和查看。

怎么使用

由于现在Nginx用的比较广泛,我用的也是Nginx,所以这里只介绍nginx的配置,其他服务器请google之。
首先是expirescache-control的配置,参看Nginx官方文档