第五章 静态资源 CDN 引入

静态请求 CDN

  • 用户将静态资源数据请求到ECS服务器,ECS服务器解析到阿里云的CDN中,CDN可以理解为一个无限大的内容磁盘缓存,本身没有文件存储。当用户访问 getItem 的一个静态资源文件的时候,会根据路由规则查看本地是否有这样的文件,如果有直接返回,没有就回源到源站,回源到下面的OSS中获取静态资源文件。
  • CDN一边返回对应的文件,一边将文件按照http指示的生命周期缓存起来,以便下次用户访问时,直接返回。

第五章 静态资源 CDN 引入_Cache Control

第五章 静态资源 CDN 引入_CDN_02

Cache Control 响应头

Cache Control 状态标志着缓存的策略

  • ​private​​:客户端可以缓存
  • ​public​​:客户端和代理服务器都可以缓存(代理服务器指的是从客户端到后端服务器所经过的中间服务器结点,比如 nginx、CDN、正向代理服务器等)
  • ​max-age=xxx​​:缓存的内容将在 xxx 秒后失效
  • ​no-cache​​:强制向服务端再验证一次(客户端缓存在本地,下次使用缓存时要向服务器请求验证是否可以使用缓存)
  • ​no-store​​:不缓存请求的任何返回内容

第五章 静态资源 CDN 引入_全页面静态好_03

客户端向服务器验证是如何做的呢 ?

有效性判断

  • ​ETag​​:资源唯一标识
  • 将请求的内容进行MD5或Hash的加密,生成一串资源唯一标识符,在第一次返回内容的时候,加上ETag返回给客户端浏览器。
  • 下一次请求时,发送HTTP请求带上ETag,与服务器本地的ETag做验证,若符合就返回状态码304 (Not Modified) ,表示缓存是有效的,客户端可以直接使用。
  • ​If-None-Match​​:客户端发送的匹配Etag标识符
  • ​Last-modified​​:服务端响应资源的最后修改时间
  • ​If-Modified-Since​​:客户端发送的匹配资源最后修改时间的标识符

整个客户端向浏览器请求流程如下:

第五章 静态资源 CDN 引入_静态请求_04

首先用户请求资源,

  • 先判断URL本地是否有缓存,如果没有就直接向服务器请求,然后返回。
  • 如果有,判断缓存是否过期 (​​max-age​​),若没有过期,则直接使用缓存资源。
  • 如果有​​max-age​​​ 但过期了,则优先判断​​ETag​​​:有​​ETag​​​ 的话就向服务器请求​​If-None-Match​​​,请求带上​​ETage​​。
  • 若没有​​ETag​​​,则判断是否有​​Last-Modified​​​,然后向服务器请求​​If-modified-since​​​(客户端发送的匹配资源最后修改时间​​If-None-Match​​​如果早于服务器响应资源修改时间​​Last-Modified​​,则资源无效已经被修改,如果晚于则资源有效)
  • 服务器返回的是304表示资源没有修改,则本地缓存可直接使用;如果返回200,表示资源被修改,需要向服务器发起请求

浏览器三种刷新方式

  • 回车刷新或a标签连接:看cache-control对应的max-age是否仍然有效,有效就直接使用本地缓存,如果cache-control中为no-cache,则进入缓存协商逻辑(指判断ETage或LastModified这种方式)
  • F5刷新或 command+R 刷新:去掉cache-control中的max-age或直接设置max-age为0,然后进入缓存协商逻辑
  • 强制刷新 ctrl+F5 或 command+shift+R 刷新:去掉 cache-control 和协商头(带ETage或Last-Modified),强制刷新,从服务器获取资源

缓存协商机制:比较 last-modified 和 ETag 到服务端,若服务端判断没变化则304不返回数据然后客户端直接使用本地缓存,否则200返回数据

CDN 自定义缓存策略

  • 可自定义目录过期时间(CDN自身向源站OSS做回源的时间)
  • 可自定义后缀名过期时间(针对不同后缀名设置过期时间)
  • 可自定义对应权重(设置用自定义后缀名过期时间/自定义目录过期时间二者使用的权重)
  • 可通过界面或api强制cdn对应目录刷新(不一定保证成功)

第五章 静态资源 CDN 引入_Cache Control_05

静态资源CDN部署策略

部署策略一

如果静态资源文件(css,js,img)文件名不变,采用max-age缓存时间设置后,如果在缓存有效时间内发生版本更新,比如重大故障或更新,如果全都是让用户来手动刷新浏览器,清缓存,这样体验不好,有以下几种部署策略:

  • css,js,img等元素使用带版本号部署,例如a.js?v=1.0不便利,且维护困难(如果单纯改某个文件版本,其他文件是否更新版本号会难以维护)。
  • html内嵌css,js,img这些资源,必须设置成​​no-cache​​,向服务器做缓存协商机制。html一般采用强推的概念,可以设置max-age,但每次请求都会让CDN全部失效,然后回源,这样将 max-age 设置一个短的时间后,用户就有版本更新
  • css,js,img等元素使用带摘要部署:例如a.js?v=45edw存在先部署html还是先部署资源的覆盖问题。
  • 给资源文件名后加一个部署摘要(一段字符串,如果文件没变化,摘要也不改变),但会存在问题。
  • 情况1:先部署资源文件后部署html
  • 某个js文件发生变化,更改摘要后如果js先部署,js会覆盖老版本,此时html引用的还是老的js文件,有可能导致不兼容问题;
  • 情况2:先部署html后部署资源文件
  • 先部署html会引用新的js,而此时服务器还是老的js等,容易出错。
  • (推荐)css,js,img 等元素使用摘要做文件名部署,例如45edw.js,新老版本并存,且可回滚,资源文件部署完成后再部署html。

部署策略二

  • 对应静态资源保持生命周期内不会变,max-age可设置的很长,无视失效更新周期
  • html文件设置no-cache或者较短的max-age,以便于更新
  • html文件仍然设置较长的max-age,依靠动态的获取版本号请求发送到后端,异步下载最新的版本号的html后展示渲染在前端
  • 动态请求也可以静态化成json资源推送到cdn上
  • 依靠异步请求获取后端节点对应资源状态做紧急下架处理
  • 可通过跑批仅仅推送cdn内容使其下架等操作

全页面静态化

html,css,js 静态资源cdn化 -> js ajax动态请求cdn化(将请求变成静态文件发送到cdn)–> 全页面静态化

**定义:**在服务端完成html,css,甚至js的load并渲染成纯html文件后直接以静态资源的方式部署到cdn上

phantomjs

首先 phantomjs 是一个无头浏览器,可以借助其模拟 webkit js 的执行

  • 修改需要全页面静态化的实现,采用initView和hasInit方式防止多次初始化
  • 编写对应轮询生成内容方式
  • 将全静态化页面生成后推送到 cdn

总结:经过全页面静态化以后,从以前刷新 ajax 请求填充到 html 这个过程变成了已经执行好的静态html页面