PaulChess/MyBlog

组内分享: Http相关知识

Opened this issue · 1 comments

组内分享http相关问题:

  1. http缓存方式和区别, 如expires、max-age、no-cache
  2. http报头常见字段的用途,和注意事项, 如: contet-type对传参方式的影响,formatdata和payload
  3. jsonp原理
  4. cookie和token的区别
  5. 为什么我们静态资源所使用的缓存方案是max-age,而不是协商缓存
  6. 不同的请求数据类型具体的表现,如何通过字段判别缓存、跨域等
  7. axios在项目中具体应用的优劣、针对项目中axios使用有何技巧、有何优化方向, 如:token热更新,超时自动重试

1.什么是缓存?

缓存是一种保存资源副本并在下一次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。

2.缓存的种类

大致分为两类: 私有缓存共享缓存。MDN上主要介绍了浏览器与代理缓存,除此之外还有网关缓存cdn缓存反向代理缓存负载均衡器等部署在服务器上的缓存方式。

3. 缓存控制

1.Cache-control控制头

HTTP/1.1定义的 Cache-Control 头用来区分对缓存机制的支持情况, 请求头和响应头都支持这个属性。通过它提供的不同的值来定义缓存策略。

  • 没有缓存 no-store
    缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。
Cache-Control: no-store
  • 缓存但重新验证
    每次有请求发出时,缓存会将此请求发到服务器(该请求应该会带有与本地缓存相关的验证字段),服务器端会验证请求中所描述的缓存是否过期,若未过期(即状态码返回304),则资源才使用本地副本。
Cache-Control: no-cache
  • 私有和公共缓存
    "public" 表示该响应可以被任何中间人(比如中间代理、CDN等)缓存。若指定了"public",则一些通常不被中间人缓存的页面(如带有HTTP验证信息的页面或某些特定状态码的页面)将会被缓存。
    "private" 表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。
Cache-Control: private
Cache-Control: public
  • 过期 !!! max-age , expires..
    过期机制中,最重要的的指令是max-age=<seconds>,表示资源能被缓存的最大时间,相较于Expires, max-age距离请求发起的时间的秒数,针对应用中那些不会改变的文件,通常可以手动设置一定的时长来保证缓存有效,例如图片,css,js等静态资源。
Cache-Control: max-age=31223122
  • 验证方式 must-revalidate
    缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用。
Cache-Control: must-revalidate

2.Pragma头

PragmaHTTP/1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control: no-cache相同。但是HTTP的响应头没有明确定义这个属性,所以它不能拿来完全替代HTTP/1.1中定义的Cache-control头。通常定义Pragma以向后兼容基于HTTP/1.0的客户端。

4. 新鲜度与驱逐算法

由于缓存只有有限的空间用于存储资源副本,所以缓存会定期地将一些副本删除,这个过程叫做缓存驱逐
另一方面,当服务器上面的资源进行了更新,那么缓存中的对应资源也应该被更新,由于HTTP是C/S模式的协议,服务器更新一个资源时,不可能直接通知客户端更新缓存,所以双方必须为该资源约定一个过期时间,在该过期时间之前,该资源(缓存副本)就是新鲜的,当过了过期时间后,该资源(缓存副本)则变为陈旧的。驱逐算法用于将陈旧的资源(缓存副本)替换为新鲜的。
一个陈旧的资源(缓存副本)是不会直接被清除或忽略的,当客户端发起一个请求时,缓存检索到已有一个对应的陈旧资源(缓存副本),则缓存会先将此请求附加一个If-None-Match头,然后发给目标服务器,以此来检查该资源副本是否是依然还是算新鲜的,若服务器返回了 304 (Not Modified)(该响应不会有带有实体信息),则表示此资源副本是新鲜的,这样一来,可以节省一些带宽。若服务器通过 If-None-Match 或 If-Modified-Since判断后发现已过期,那么会带有该资源的实体内容返回。
image

对于含有特定头信息的请求,会去计算缓存寿命。比如Cache-control: max-age=N的头,相应的缓存的寿命就是N。
通常情况下,对于不含这个属性的请求则会去查看是否包含Expires属性,通过比较Expires的值和头里面Date属性的值来判断是否缓存还有效。
如果max-age和expires属性都没有,找找头里的Last-Modified信息。如果有,缓存的寿命就等于头里面Date的值减去Last-Modified的值/10。

// 缓存失效时间计算公式:
// 其中,responseTime表示浏览器接收到此相应的那个时间点。
expirationTime = responseTime + freshnessLifeTime - currentAge

5. 改进资源

为了优化缓存,过期时间设置得尽量长是一种很好的策略。对于定期或者频繁更新的资源,这么做是比较稳妥的,但是对于那些长期不更新的资源会有点问题。比如网页上引入的一些js/css文件,当它们变动时需要尽快更新线上资源。
web开发者发明了一种叫revving的技术。不频繁更新的文件会使用特定的命名方式:在URL后面(通常是文件名后面)会加上版本号。加上版本号后的资源就被视作一个完全新的独立的资源,同时拥有一年甚至更长的缓存过期时长
但是这么做也存在一个弊端,所有引用这个资源的地方都需要更新链接。web开发者们通常会采用自动化构建工具在实际工作中完成这些琐碎的工作。当低频更新的资源(js/css)变动了,只用在高频变动的资源文件(html)里做入口的改动。

参考资料:
1.MDN Web Docs HTTP缓存