浏览器缓存机制

kingwbs 2019-06-20

浏览器缓存基本认识

分为强缓存协商缓存

浏览器在加载资源的时候,会根据这个资源的http header判断它是否命中强缓存,如果命中,就直接从缓存中读取资源,不会发请求到服务器。

当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端一句资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源。

当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

强缓存原理

强缓存是利用Expires或者Cache-Control这两个http response header实现的,它们都用来表示客户端缓存的有效期,请求响应返回的状态为200

Expire

Expire:Thu, 31 Dec 2037 23:55:55 GMT

1)浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Expires的header;

2)浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的Expires跟当前的请求时间比较,如果请求时间在Expire指定的时间之前,就能命中缓存;

3)如果缓存没有命中,浏览器直接从服务器加载资源时,Expire Header在重新加载的时候会被更新

缺点
Exipires是较老的强缓存管理header,由于它是服务器返回的一个绝对时间,在服务器时间与客户端时间相差较大的时候,缓存管理容易出现问题,比如随意修改一下客户端时间就能影响缓存命中的结果。

Cache-Control

Cache-Control: max-age = 315360000

1)浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Cache-Control的header;

2)浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来

3)浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,根据它第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间再过期时间之前,就能命中缓存;

4)如果缓存没有命中,浏览器直接从服务器加载资源时,Cache-Control Header 在重新加载的时候会被更新。

Expire和Cache-Control的联系和区别

前者描述的是绝对时间,后者是相对时间

可以只启用一个,也可以同时启用,同时存在时,Cache-Control优先级高于Expire

如何设置强缓存

1)通过代码方式,在web服务器返回的相应中添加Expires和Cache-Control Header;

2)通过配置web服务器的方式,让web服务器在响应资源的时候统一添加Expires和Cache-Control Header

协商缓存的原理

请求响应返回的状态为304并且会显示一个Not Modified的字符串,协商缓存是利用的是Last-Modified,If-Modified-since和ETag,If-None-Match这两对Header来管理的

Last-Modified,If-Modified-since原理

Last-Modified: Tue, 12 Jan 2016 03:08:53 GMT
If-Modified-Since: Tue, 12 Jan 2016 03:08:53 GMT

1)浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间;

2)浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值;

3)服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header;

4)浏览器收到304的响应后,就会从缓存中加载资源;

5)如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值;

缺点:

有时候服务器上资源其实有变化,但是最后修改时间却没有变化,而这种问题又很不容易被定位出来,而当这种情况出现的时候,就会影响协商缓存的可靠性

ETag, If-None-Match原理

ETag: "17fd8-5291a5f96fd20"

1)浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上ETag的header,这个header是服务器根据当前请求的资源生成的一个唯一标识,这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间没有关系,所以能很好的补充Last-Modified的问题;

2)浏览器再次跟服务器请求这个资源时,在request的header上加上If-None-Match的header,这个header的值就是上一次请求时返回的ETag的值;

3)服务器再次收到资源请求时,再根据资源生成一个新的ETag,与浏览器传过来If-None-Match比较,如果这两个值相同就说明资源没有变化,否则就是有变化;如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化

4)浏览器收到304的响应后,就会从缓存中加载资源。

注意的问题

分布式系统里多台机器间文件的Last-Modified必须保持一致,以免负载均衡到不同机器导致比对失败;

分布式系统尽量关闭掉ETag(每台机器生成的ETag都会不一样);

相关推荐