HTTP缓存机制

简介

web缓存大致可以分为:数据库缓存,服务器端缓存(代理服务器缓存,CDN缓存),浏览器缓存。
浏览器缓存也包含很多内容:HTTP缓存,indexDB,cookie,localStorage等等,这里我们只讨论HTTP缓存相关内容。

在具体了解HTTP缓存之前先来明确几个术语:
缓存命中率:从缓存中得到数据的请求数与所有请求数的比率,理想状态是越高越好。
过期内容:超过设置的有效时间,被标记为“陈旧”的内容。通常过期内容不能用于回复客户端的请求,必须重新向源服务器请求新的内容或者验证缓存的内容是否仍然准备。
验证:验证缓存中的过期内容是否仍然有效,验证通过的话刷新过期时间。
失效:失效就是把内容从缓存中移除,当内容发生改变时就必须移除失效的内容。

浏览器缓存主要是HTTP协议定义的缓存机制,一般应用广泛的是用HTTP头信息控制缓存。

附:浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。缓存要解决的核心问题为减少客户端对服务器的http请求,提升性能。试想,像jquery、bootstrap这种更新不频繁的资源当然没有必要每次都从服务器上获取,实际上大部分静态文件在下一次内容更新之前都没有必要再走一遍网络从服务器获取。
所以根据上面的特点,浏览器缓存有下面的优点:① 减少冗余的数据传输;② 减少服务器负担;③ 加快客户端加载网页的速度。

HTTP头信息控制缓存

根据是否需要重新向服务器发起请求来分类,将其分为两大类:强缓存,协商缓存。强缓存如果命中缓存则不需要和服务器端发生交互,而协商缓存不管是否命中都要和服务器端发生交互。强制缓存的优先级高于协商缓存。

匹配流程是:浏览器发送请求之前,根据Expire或Cache-Control判断是否命中强缓存,如果命中就从缓存获取资源;如果没有命中就发送请求,根据Last-Modified或Etag判断是否命中协商缓存,如果命中就从缓存中获取资源,否则从服务器端获取资源。

强缓存

可以理解为无需验证的缓存策略,就是说当请求一个资源时,直接从本地的浏览器缓存中读取,不发起http请求。对于强缓存来说,响应头中有两个字段Expires/Cache-Control来表明规则。


Expires:指缓存过期的时间,超过了这个时间就代表资源过期。有一个问题是由于使用具体时间,如果时间表示出错或者没有转换到正确的时区都可能造成缓存生命周期出错。并且Expires是HTTP/1.0的标准,现在更倾向于用HTTP/1.1中定义的Cache-Control。两个同时存在时也是Cache-Control的优先级更高。

Cache-Control:可以由多个字段组合而成,主要有以下几个取值:
1. max-age:指定一个时间长度,在这个时间段内缓存是有效的,单位是s。例如设置:

Cache-Control:max-age=31536000

也就是说缓存有效期为(31536000 / 24 / 60 * 60)天,第一次访问这个资源的时候,服务器端也返回了Expires字段,过期时间是一年后,在没有禁用缓存并且没有超过有效时间的情况下,再次访问这个资源就命中了缓存,不会向服务器请求资源而是直接从浏览器缓存中取。
2. s-maxage:同max-age,覆盖max-age,Expires,但仅适用于共享缓存,在私有缓存中被忽略。
3. public:表明响应可以被任何对象(发送请求的客户端,代理服务器等等)缓存。
4. private:表明响应只能被单个用户(可能是操作系统用户,浏览器用户)缓存,是非共享的,不能被代理服务器缓存。
5. no-cache:强制所有缓存了该相应的用户,在使用已缓存的数据前,发送带验证器的请求到服务器。不是字面意思上的不缓存。
6. no-store:禁止缓存,每次请求都要向服务器重新获取数据。

协商缓存

缓存的资源到期了,并不意味着资源内容发生了改变,如果和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。

浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回200就相当于重新请求了一遍资源并替换旧资源。最后,更新缓存头信息。



注意:如果响应头中有Last-modified而没有Expires或Cache-Control时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以Last-modified要记得配合Expires和Cache-Control使用。



当本地缓存过期后,客户端如何知到该使用上述哪种方式呢?其实,在客户端第一次请求资源时,服务器需要带上Last-Modified与ETag,然后缓存起来,当缓存失效重新进行新鲜度检查时,这两个头部就可以派上用场了。一般来说,ETag的优先级高于Last-Modified。
1、If-None-Match和Etag

Etag:是服务器端对于某个资源的某个特定版本的一个标识符
If-None-Match:如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变

If-None-Match: W/"162c-1582aaed638" & Etag: W/"162c-1582aaed638"

浏览器初次请求某个资源时,服务器http响应头中会添加一个Etag信息,当浏览器再次请求该资源时,会在request header中加入If-None-Match,其值就是之前收到的Etag值,如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag。

2、If-Modified-Since和Last-Modified

If-Modified-Since的值是浏览器端缓存内容的最后修改时间,属于请求头
Last-Modified的值是服务器端资源的最后修改时间,属于响应头

If-Modified-Since: Fir, 02 Dec 2016 17:20:11 GMT & Last-Modified: Fir, 02 Dec 2016 17:20:11 GMT

If-Modified-Since的值发送到服务器去,服务器会把这个时间与服务器上实际文件的Last-Modified的值进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。

Etag和Last-modified区别
  1. 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
  2. Last-modified只能精确到秒。
  3. 一些资源的最后修改时间改变了,但是内容没改变,使用Last-modified看不出来内容没有改变。
  4. Etag的精度比Last-modified高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供Etag的话,必须先对Etag进行Conditional Request。
    注意:实际使用Etag/Last-modified要注意保持一致性,做负载均衡和反向代理的话可能会出现不一致的情况。计算Etag也是需要占用资源的,如果修改不是过于频繁,看自己的需求用Cache-Control是否可以满足。

实际应用

回到实际应用上来,首先要明确哪些内容适合被缓存,哪些不适合。

考虑缓存的内容:css样式文件,js文件,logo,图标,html文件,可以下载的内容
不应该被缓存的内容:业务敏感的get请求

可缓存的内容又分为几种不同的情况:

不经常改变的文件:给max-age设置一个较大的值,一般是max-age=31536000;比如引入一些第三方文件,打包出来的带有hash后缀的css,js文件。一般来说文件内容改变了,会更新版本号,hash值,相当于请求另一个文件。
标准中规定max-age的值最大不超过一年,所以设成max-age=31536000。至于过期内容,缓存区会将一段时间不用的文件删除。

可能经常需要变动的文件:Cache-Control:no-cache / max-age=0
比如入口index.html文件,文件内容改变但名称不变的资源。选择Etag或Last-Modified来做验证,在使用缓存资源之前一定会去服务器端做验证,命中缓存时会比第一种情况慢一点点,毕竟还要发请求进行通信。

清除缓存

1. Math.random()
$.ajax({url:'test.php?'+parseInt(Math.random()*100000)}

可以采取在ajax的url后加上随机串来避免浏览器缓存,使每一次的请求都是一个新请求,从而防止浏览器从缓存中读取旧版本,

2. 加入当前时间

除了加入随机数还可以加入当前时间,同样可以使每次请求的地址都是不一样的,从而防止浏览器使用缓存。

3. ajax清除浏览器缓存
$.ajax({
     url:'www.baidu.com',
     dataType:'json',
     data:{},
     beforeSend:function(xmlHttp){ 
        xmlHttp.setRequestHeader("If-Modified-Since","0"); 
        xmlHttp.setRequestHeader("Cache-Control","no-cache");
     },
     success:function(response){
         //操作
     }
     async:false
});
4. 直接用cache:false
 $.ajax({
     url:'www.haorooms.com',
     dataType:'json',
     data:{},
     cache:false, 
     ifModified :true ,

     success:function(response){
         //操作
     }
     async:false
  });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 网络特有的延迟以及数据传输的成本,制约互联网快速获取Web资源。为此,HTTP协议引入缓存以空间换时间,使浏览器缓...
    大头8086阅读 3,056评论 2 12
  • 本文内容大多参考《图解HTTP》一书 一. 认识代理服务器 所以讲缓存为什么要先扯代理服务器?别急,让我们看一下一...
    流光号船长阅读 1,898评论 0 10
  • HTTP Headers 1. 通用首部字段:就是请求报文和响应报文都能用上的字段 2. 请求首部字段 3. 响应...
    莱斯塔特阅读 381评论 0 0
  • 时间:2016-12-12 17:51:30作者: zhongxia 零、前言 这里主要写的是理论,具体实践的比较...
    izhongxia阅读 271评论 0 1
  • 有些时候需要查看下cup信息,现在记录下罗!! 一.Android查看cup核心数 二.Android查看cup状...
    我在等你回复可你没回阅读 899评论 4 3