Skip to content

如何保证发布后 CDN 代码是最新的?如何预热? #186

@TieMuZhen

Description

@TieMuZhen

一、保证CDN加载最新资源

hashcontentHash的区别

hash一般是结合CDN缓存来使用,通过webpack构建之后,生成对应文件名自动带上对应的MD5值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的HTML引用的URL地址也会改变,触发CDN服务器从源服务器上拉取对应数据,进而更新本地缓存。

hash

hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改,并且全部文件都共用相同的hash值

chunkhash

采用hash计算的话,每一次构建后生成的哈希值都不一样,即使文件内容压根没有改变。这样子是没办法实现缓存效果,我们需要换另一种哈希值计算方式,即chunkhash

chunkhashhash不一样,它根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响

contenthash

chunkhash的例子,我们可以看到由于index.cssindex.js引用了,所以共用相同的chunkhash。但是这样子有个问题,如果index.js更改了代码,css文件就算内容没有任何改变,由于是该模块发生了改变,导致css文件会重复构建
这个时候,我们可以使用extra-text-webpack-plugin里的contenthash值,保证即使css文件所处的模块里就算其他文件内容改变,只要css文件内容不变,那么不会重复构建。只有文件自身内容发生变化,contenthash才会更新。

var extractTextPlugin = require('extract-text-webpack-plugin'),
    path = require('path')

module.exports = {
  ...
  ...
  output:{
    path:path.join(__dirname, '/dist/js'),
    filename: 'bundle.[name].[chunkhash].js',
  },
  plugins:[
    new extractTextPlugin('../css/bundle.[name].[contenthash].css')
  ]
}

html文件设置缓存方式

<!-- 设置缓存2小时,max-age指最大缓存的秒数 -->
<meta http-equiv="Cache-Control" content="max-age=7200" />
<!-- 或者这样设置永远不缓存 -->
<meta http-equiv="Cache-Control" content="no-cache" />

如何保证发布后 CDN 代码是最新的?

  • 每个文件打包输出时加上contentHash,文件内容变化时文件名必定变化。
  • index.html不要设置缓存,因为打包后index.html内引用的scirpt url发生了变化(因为 contentHash),因此可以知道最新的 js 文件。
  • CDN 配置了监听 OSS 的更新事件,文件更新时触发回源更新。

二、CDN预热

什么是预热?

首次发布的文件,主动从源站推送到CDN,让用户访问到CDN时不用回客户的源站命中。

为什么要预热?

主动从源站推送到CDN,让用户访问到CDN时不用回客户的源站命中。

假如某游戏首次发布,玩家抢着赶紧下载游戏客户端(3GB)。如果没有预热,第一批玩家在访问官网下载时,官网CNME记录解析到CDN。由于是第一次访问,CDN中缓存也没有,因此需要回源站去获取游戏客户端(3GB

影响:
首批下载的用户体验很差,因为都集中访问源站主机,源站主机的CPU利用率和带宽会跑的很高。第一批玩家下载完成后,CDN中也能够缓存了一份,第二批玩家下载就直接在CDN中命中,速度比第一批快得多。

但是等CDN缓存好完整一份游戏客户端,可能半天到1天的时间就过去了。因为第一批下载时,源站压力非常大,CDN回源的带宽可能只有几KB,几KB的速度下载2GB的文件,可能要好几天了。那么游戏开服的头几天连游戏客户端都下载不了。

在开服前,通过预热功能,将游戏安装包(3GB)从源站推送到各CDN节点,提前先缓存起来。等开服的时候,第一个玩家也能从CDN中快速获取到游戏安装包。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions