聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

6-1 静态资源CDN引入

静态请求CDN

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

CDN一边返回对应的文件,一边将文件按照http指示的生命周期缓存起来,以便下次用户访问时,直接返回。

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

整个项目的架构:

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

6-3 Cache Control响应头

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

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

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

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

有效性判断

  • ETag:资源唯一标识

    将请求进行MD5或Hash的加密,生成一串资源唯一标识符。

    下一次请求时,发送HTTP请求带上ETag,与服务器本地关于ETag做验证,符合就返回状态码304(Not Modified) ,表示缓存客户端可以直接使用

  • If-None-Match:客户端发送的匹配Etag标识符

  • Last-modified:资源最后被修改的时间

  • If-Modified-Since:客户端发送的匹配资源最后修改时间的标识符

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

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

首先用户请求资源,

1)先判断URL本地是否有缓存,如果没有直接向服务器请求,然后返回;

2)如果有,判断缓存是否过期(max-age),没有过期,直接使用缓存资源;

3)如果有max-age但过期,则优先判断ETag:有的话向服务器请求If-None-Match,请求带上ETage;

4)没有ETag,判断是否有Last-Modified,然后向服务器请求If-modified-since(客户端发送的匹配资源最后修改时间如果早于资源修改时间Last-Modified,则无效已经被修改,如果晚于则有效)

5)服务器返回的是304表示资源没有修改,则本地缓存可直接使用;如果返回200,表示资源被修改,向服务器发起请求;

6-4 浏览器三种刷新方式

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

缓存协商机制:比较last-modified和ETag到服务端,若服务端判断没变化则304不返回数据,否则200返回数据

6-5 CDN自定义缓存策略

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

阿里云CDN的缓存策略这篇文章讲的很详细

聚焦Java性能优化 打造亿级流量秒杀系统【学习笔记】05_查询性能优化技术之页面静态化

6-6 静态资源cdn部署策略

部署策略一

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

  1. css,js,img等元素使用带版本号部署,例如a.js?v=1.0不便利,且维护困难(如果单纯改某个文件版本,其他文件是否更新版本号会难以维护)

html内嵌css,js,img这些资源,必须设置成no-cache,向服务器做缓存协商机制。html一般采用强推的概念,可以设置max-age,但每次请求都会让CDN全部失效,然后回源,这样将max-age设置一个短的时间后,用户就有版本更新

  1. css,js,img等元素使用带摘要部署:例如a.js?v=45edw存在先部署html还是先部署资源的覆盖问题;

给资源文件名后加一个部署摘要(一段字符串,如果文件没变化,摘要也不改变),但会存在问题。

1) 情况1-先部署资源文件后部署html

某个js文件发生变化,更改摘要后如果js先部署,js会覆盖老版本,此时html引用的还是*s,有可能导致不兼容问题;

2) 情况2-先部署html后部署资源文件

先部署html会引用新的js,而此时服务器还是老的js等,容易出错

  1. (推荐)css,js,imh等元素使用摘要做文件名部署,例如45edw.js,新老版本并存,且可回滚,资源部署完成后再部署html;

部署策略二

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

6-7 全页面静态化

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

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

phantomjs

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

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

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