HTTP缓存是web开发中经常碰到的问题,但是之前虽然看过,那时候web开发刚开始做,概念有点儿模糊不清,所以重读了《HTTP权威指南》的缓存部分。这里对自己的理解做一下记录。
为什么要缓存
为什么要做缓存?如果你看到了这篇文章,其实心中肯定有了一个作缓存的需求和目标。缓存的目的无非就是提高用户体验,节省资源两方面。
- 提高用户体验:
从提高用户体验来讲,就是用户能够看到反馈的时间越短越好,速度越快越好。那么如何才能提高速度呢?当然是数据和用户越近越好,最好就在本地;还有就是网速越快越好,最好连接网络就能访问。我们都知道本地应用是最快的,因为所有的都在你的电脑里了,不需要再费劲去网上下载了。缓存的目的就是为了尽量完成这个工作而设计的。 - 节省资源:
这个怎么说呢,如果你要访问一个网站,第一次你肯定没有这些数据,但是如果访问后所有的数据都保存在了本地,或者离你很近的地方,就省得在网络的海洋漫游过来了,这当然就节省了不少流量,当然你的计费方式是按带宽来的,多少流量无所谓,可是对于提供网站服务的供应商来说这些都是白花花的银子啊,能剩就剩,节约每一个铜板
嘛。缓存的机制
这里只介绍基于HTTP协议的缓存。也许做web开发的都听过expires
,cache-control
,If-Modified-Since
等缓存控制的HTTP头,这些眼花缭乱的头真让让人头晕啊,到底他们之间是什么关系,写了那么多,但是缓存是不是生效了?怎么生效的啊?带着这些疑问我也仔细阅读了一下书里的内容。其实一幅图可以说明很多问题:
通过这个流程图我们可以看出有三个方向:
- 未找到缓存(黑色线)
当没有找到缓存时,说明我们本地并没有这些数据,这种情况一般发生在我们首次访问网站,或者以前访问过,但是清除过缓存后。这时浏览器没有这些数据,浏览器就会先访问服务器,然后把服务器上的内容取回来,内容取回来以后,就要根据情况来决定是否要保留到缓存中了。这个地方与cache-control
字段的内容有关系。 - 缓存未过期(蓝色线)
缓存未过期,指的是本地缓存没有过期,不需要访问服务器了,直接就可以拿本地的缓存作为响应在本地使用了。这样节省了不少网络成本,提高了用户体验过。这个内容跟expires
字段和cache-control
有密切的联系。 - 缓存已过期(红色线)
缓存过期,是根据expires
和cache-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之。
首先是expires
和cache-control
的配置,参看Nginx官方文档