现在做的项目(bingo cooking)的客户端需要下载若干个配置文件。这些文件大多与游戏内容(展现)和玩法(数值)相关。
现在的实现是这样的,客户端通过RPC请求服务端(实现游戏核心玩法的进程),请求中带着文件名和文件md5值。服务端比对之后,如果md5值相同,无需下载;否则,返回新的配置文件内容。这是前人的做法,显然使用的是IDC流量。在每次发了新版本后或者运营导量的过程中,配置文件下载是最频繁的(每个新玩家要下载多个文件)。随着游戏的持续开发,配置文件越来越多、越来越大(现在有大约3M字节)。我觉得到了该改造的时候了,应该改为使用CDN。通过CDN下载配置文件,就可以消除“下载配置”给服务端带来的压力(可能是短时间内的,也可能持续一段时间)。
技术细节
- C/S有共用的配置内容,而且这些配置内容中的一部分是要求可以“热更新”的。这款游戏的核心玩法基于房间和局,也就是一个房间内一局接一局地持续进行游戏。核心玩法的数值相关的配置,就是C/S共用的,而且是要求可以“热更新”的,所以这部分配置如果修改了,要在一局游戏开始时重新加载,并通过某种方式(推/拉)同步给客户端,还是要走IDC流量。这部分配置的热更不会经常发生。
- 同时存在多个不同版本的S,一个S版本可能同时服务于多个C版本,在CDN里设计配置文件目录的时候必须考虑到这一点。
改造思路如下
CDN
- 配置文件目录按照<platform>/<client_version>/<date>-<time>的模式创建
- 对压缩后明显变小的文件(相对较大的文本文件)予以压缩
- 目录中额外放一个文件(以下简称a),该文件中记录当前目录下每个文件的md5值(或SHA256 Checksum)。如果是压缩文件,记录压缩文件的md5值(或SHA256 Checksum)。a用于快速比对文件,以减少不必要的下载。
- 上传了新配置之后,刷新CDN,保证最新的配置传递到叶子节点。
服务端
- 增加一个配置文件(以下简称n)
- 记录CDN URL
- 记录当前S版本可以服务的不同客户端(以<platform>和<client_version>区分)对应的CDN目录(<date>-<time>)
- 记录服务端使用的最新配置文件的目录
- 服务端热更配置文件流程
- CDN中先创建新目录,上传新配置文件,并把新目录写到文件n中。
- 服务端进程工作路径下新建一个目录(按照<date>-<time>的模式拼接),把最新的配置文件放在该目录中。 再把新目录写到文件n中。
- 通过rpc通知服务端进程重新加载文件n中的内容,并“热更”配置。
客户端
- 当C登录时,要请求配置文件下载目录。S根据C的<platform>和<client_version>返回对应的资源文件下载地址前缀:cdn-url/platform/client-version/date-time
- C先下载a(即cdn-url/platform/client-version/date-time/a),然后对比本地文件a_local(第一次使用该下载策略时没有这个文件),在内存中生成差异集(即要增加和修改的所有文件名)。然后拼接文件下载地址并下载。每下载成功一个文件就记录到a_local中,直到需要下载的文件都下载完成(或至少有一个文件多次尝试下载都失败后认定整体失败)。
发布顺序
- 先更新CDN
- 再更新服务端
- 最后发布客户端(如果只是服务端热更配置就没有这一步了)