App动态配置探讨

一、背景

App开发中一个比较常见的问题就是动态化,有时我们会需要程序的某一个逻辑可以动态改变而不需要发版本让用户重新安装。例如,App中的某个WebView有一个url白名单,我们希望它可以动态改变。这是个常见的需求,现在无论是技术面上还是产品上大家都在讲一个动态化,所以一波接一波出了各种插件化,甚至是ReactNative、weex、微信小程序等等这些轮子。

但是在实际中需要考虑到很多的业务特点,使得我们在统一化个性化的时候比较难以选择,半年前天猫的技术博客就出了这篇文章–动态调整的基础 —— 配置中心,里面介绍了阿里的团队在这方面的实践经验。今天我以一个遇到的实际需求为例,总结下我的想法。

二、需求&目标:设计一个动态配置中心

  • 需求:支持不同业务、不同平台、不同版本(一般是版本的范围),按需动态下发配置。这里业务可以是不同的App、也可以是同一个App里面不同的模块,或者不同的SDK。

  • 目标:业务方(App开发者)可以自助到配置中心添加新的配置项或者修改以前的配置,按需下发到客户端。

数据模型

这里参考天猫动态配置的设计,我的动态配置中心也有下面两个的数据模型:

  • 1.配置的数据结构

这是客户端希望拿到的下发配置信息,这里我的需求就是一个key-value形式的json字符串,value里面是客户端可以自己解析出来使用的结构即可。

1
2
3
4
"base_setting": {
"key_1": "value_1",
"key_2": "value_2"
}
  • 2.元信息(meta-info):业务(bizType) -> 平台(platform) -> 版本(version)

元信息代表着按需选择配置的条件。例如,对于同一个配置项key_1,对于业务1,它的值是0,对于业务2,它的值是1。或者对于配置项key_2,不会下发给业务1,只下发给业务2。这两类情况都应该能够在配置中心实现配置。

此外,业务->平台->版本,这三个元信息之间的优先级顺序关系一定要明确,例如,业务1下面可以有iOS、Android两个平台;iOS下面又可以有1.0.0、2.0.0等多个版本。因此我认为版本的配置优先级要高于平台,平台的配置优先级要高于业务。

三、数据关系的设计

数据关系如何设计,取决于两点:

  • 1.每一项配置是如何生成的?

(1)当用户添加一个新的配置时,需要添加它的key(下发的key)、defaultValue(默认值)、name(语义上可读配置名称)

(2)然后根据需要,按照业务 -> 平台 -> 版本的顺序,逐级地选择这个配置支持的元信息。每一步选择时都需要设定一个单独的value。这里可以不用每一级元信息都要选择,只要选择到了第一级的业务,客户端就已经可以拿到这个配置了,如果需要更加细粒度的控制配置的value,才需要选择第二级的平台版本

(3)把这个配置,和它对应的业务、平台、版本这三个元信息关系,以及各个元信息下面的value都存储下来。所以配置是直接关联着业务、平台、版本这3个元信息的。

(4)存储业务、平台、版本之间的对应关系,这样才可以明确在逐级选择配置时,每一级都有哪些元信息。这里我实际中存储的是版本范围信息和平台的关系,如bizA | Android | 1.0.0-2.0.0bizA | iOS | 1.0.0 - 2.0.0。其实在创建每一级元信息的setting-value之前,就应该建立好了这个关系。

  • 2.对于每一个请求,配置中心是如何处理、最后得到属于这个请求的配置?

当配置中心的Server接收到一个请求时:

(1)提取出元信息:业务(bizType)、平台(platform)、版本(version)

(2)根据业务、平台、版本找到和它关联的所有配置项。

结合一个实例理解上面的两点:假设有2种业务,2个平台,2个版本范围,那么元信息的各种组合最多就是8种,所以每一个配置项的取值最多就是8种,我们可以选择不给某一种元信息下发这个配置,或者下发它独立的配置值。

四、总结

在设计过程中,其实就是要解决:配置结构长什么样,需要哪些元信息,元信息之间的关系是什么样的,怎么保存元信息之间的关系。这里我的需求比较简单,想到的方案也可能不是很好。实际中可能还有更多元信息,例如如果含有渠道ID,我们还可能加一个app_setting来覆盖base_setting。希望可以见到更多关于这方面的讨论和分享。