背景
使用nginx做服务器访问静态资源时,更改一个js配置文件并没有更新页面,然后debug了一下发现根本没有请求服务器,而是从本地直接读取,连304这个流程也没有,所以对这个缓存的概念又模糊了。
image.png image.png
http缓存分类
http缓存分为强制缓存和协商缓存
image.png
强制缓存
当缓存数据库中已有所请求的数据时,客户端直接从数据库读取数据。当缓存数据库中没有所请求的数据时,客户端才会从服务端获取
协商缓存
客户端会先从缓存数据库中获取到一个缓存数据的标识,得到标识后请求服务端验证标识是否失效,如果没有失效服务端会返回304,此时客户端再从缓存中读取数据,如果失效,服务端会返回跟新的数据。
强制缓存
image.png当命中强制缓存后,浏览器不会去请求服务器,而是直接使用本地缓存的资源,并返回状态码200(缓存来源)。是否命中强制缓存是由响应头中的expires和Cache-Control控制
如果强制缓存命中以后,才会出现之前背景中出现的问题:
image.png
EXPIRES
expires是http1.0的标准,表明服务器的过期时间,是格林威治时间,当请求的时候客户端的时间超过expires标识的时间时,就会去请求服务器。
可以看到,当请求的时候客户端的时间超过expires标识的时间时,就会去请求服务器,但是这个其实是存在问题的,当用户的系统时间改到这个标识的时间之后,就永远不会命中这个强制缓存。所以Cache-Control就诞生了。
CACHE-CONTROL
Cache-Control是http1.1的产物,他可以看成是expries的补充。
Cache-Control的属性:
- max-age: 设置缓存的最大的有效时间,单位为秒(s)。max-age会覆盖掉expires。
- s-maxage: 设置代理服务器缓存的最大的有效时间,单位为秒(s)。s-maxage会覆盖掉max-age。
- public: 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
- private: 只有发起请求的浏览器可进行缓存。
- no-cache: 虽然字面意义是“不要缓存”。但它实际上的机制是,仍然对资源使用缓存,也就是使用协商缓存。
- no-store: 所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存。
- must-revalidate: 如果你配置了max-age信息,当缓存资源仍然新鲜(小于max-age)时使用缓存,否则需要对资源进行验证
判断缓存是否过期的步骤:
查看是否有cache-control的max-age / s-maxage,如果有,则用服务器时间date值 + max-age/s-maxage 的秒数计算出新的过期时间,将当前时间与过期时间进行比较,判断是否过期。如果没有则用expires 作为过期时间比较。
image.png
强制缓存总结
浏览器的强制缓存由响应头中的expires和Cache-Control控制。当Cache-Control中有max-age/s-maxage时则用服务器时间date值 + max-age/s-maxage 的秒数计算出新的过期时间;否则用expires作为资源的过期时间。
协商缓存
image.png协商缓存就是得与服务器商量一下是否使用缓存,命中协商缓存的话会返回状态304。
协商缓存由响应头中的Last-Modified和ETag还有请求头中的If-Modified-Since和If-None-Match控制
参数详解
-
Last-Modified:标示这个响应资源的最后修改时间。
-
If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age/s-maxage),发现资源具有Last-Msodified声明,则向服务器请求时带上头 If-Modified-Since(即响应头中的Last-Modified值),表示请求时间。这个时候服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源有被改动过,将新资源返回并返回状态200,否则返回304表示资源没被更新使用缓存即可。
-
Etag:服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。例如在Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
-
If-None-Match:当资源过期时(使用Cache-Control标识的max-age/s-maxage),发现资源具有Etage声明,则向服务器请求时带上头If-None-Match(即响应头中Etag的值)。服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304(注意:服务器会优先验证If-None-Match)。
Etag的作用
- Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
- 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
- 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
协商缓存小结
当浏览器没命中强制缓存时,会和服务器协商是否使用缓存,这个就是协商缓存,协商缓存由响应头中的Last-Modified和ETag还有请求头中的If-Modified-Since和If-None-Match控制。命中协商缓存的资源,服务器会返回304
CDN缓存
CDN即Content Delivery network,内容分发网络。CDN可以理解为一个火车票的代售点,用户在浏览网站的时候,CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求。例如,上海用户想要访问我https://www.suhongyan.xyz上的一个资源,这个时候,刚好我在上海有台CND服务器,用户的请求直接会被打到这台上海的CDN服务器上,而不会跑到北京深圳的服务器上去请求我的资源,这样就加快了服务器的相应时间。也就是相当于服务器和用户之间的cache。
CDN缓存策略
和浏览器缓存机制类似,CND也有一套类似的缓存策略,这套缓存策略会决定CDN服务器什么时候去更新自己的资源。
上文所说的Cache-Control的max-age头可以告知文件在浏览器的缓存时间,在max-age指定的时间内,浏览器会直接使用本地缓存,而不会请求服务器,CDN采取了类似的机制,你只要把CDN节点看成浏览器,源服务器看成浏览器需要请求的服务器即可,此时,源服务器的max-age头决定了资源在CDN节点本地缓存的时间,有一点差别的是,CDN规定了一个自定义协议,也就是上文说的s-maxage,若源站该s-maxage存在,会优先使用s-maxage作为CDN的缓存时间。
image.png
网友评论