从移动端的配置说起

作者: Neo_joke | 来源:发表于2018-12-02 21:20 被阅读20次

    出了什么问题

    大多数客户端都有远程配置的功能和需求,项目规模由小到大以后,对客户端动态配置的需求就会迅速增加。就会出现新的问题和需求。

    • 配置项逐渐增多,配置内容大小逐步增大
    • 客户端版本逐渐曾多,版本之间的配置差异较大,配置管理混乱,牵一发而动全身
    • 运营和产品对业务配置的需求逐渐增加,需要有独特的配置关联逻辑
    • 配置不断庞大,下发到客户端的时候需考虑流量问题
    • 配置服务端考虑并发问题
    • 配置动态下发,考虑不同的更新策略,考虑安全性

    历史及现状

    可能很多移动端的开发者都有这样的经历:
    通过某一个接口,获取某一业务功能的配置信息,有时候需要根据业务触发的逻辑,在不同的时机调用接口,获取配置,又有些时候需要把客户端的一些信息,如版本号、时间、上次的缓存等等,传入接口获取最新配置,这其实就是最简单的远程配置需求,根据配置相关条件,通过不同的更新策略,获取远程配置。

    1.0阶段

    设计接口如下:

    $ curl https://api.xxx.com/v0/configuration/getMessageConfig?appVersion=1.0.0&platform=iOS&messageType=1 \
    -H "SS-Cache-Version: XXXXXXXXX"
    
    {
        "code":"0",
        "result":{
            "config_value":"******",
            "cache_version":"******"
        }
    }
    

    通过不断开发新的接口,满足各个业务线对配置功能需求。
    优点:需求较少的时候,开发特别快
    缺点:客户端需要不断开发新的API调用,服务端则需要不断开发新接口,配置与客户端的关联信息发生变化,API则需要进行升级,而客户端存在多版本并存的情况,老版本API也无法下线,占用服务端资源。

    2.0阶段

    为减轻服务端开发依赖,有的开发者通过使用第三方开发平台进行配置分发。
    例如,使用umeng的在线参数进行远程配置

    image

    优点:
    无需服务端开发,第三方实现SDK与其服务端的通信,不需要做客户端开发

    缺点:
    无法与客户端信息做相关,只能通过约定配置参数名称例如 配置项名称+平台名称+客户端版本作为配置项名称,做硬关联,大量生成重复配置项。无法控制更新策略。业务相关配置放置在第三方平台,无法保证数据安全。

    3.0阶段

    由此前的经历和需求痛点,我们设计出新的移动端配置中心。
    主要有如下功能

    1. 支持配置客户端信息与配置项相关,做到不同的客户端获取不同的配置项
    2. 支持配置增量更新
    3. 支持客户端配置加密下发,保证安全
    4. 提供统一后台配置界面,方便进行配置的管理
    5. 做到配置更新,主动推送到客户端
    6. 支持配置回滚,删除恢复

    解决思路

    根据以上需求,整体方案的解决思路可以是如下这样:

    1. 移动端开发远程配置组件,用于获取最新的后端配置
    2. 客户端与接口交互的时候,将诸如appid(存在对个应用)、appVersion、platform、channel(渠道)、systemVersion等基础信息传入接口,方便配置项与其关联
    3. 客户端与接口交互的时候,支持全量更新,支持通过生成增量包进行增量更新
    4. 服务端与客户端进行数据传输的时候,进行通信数据加密
    5. 对于服务端,客户端提供定时配置同步策略,服务端通过推送和长连接通讯主动推送配置
    6. 配置项后台的增删改查,都采取版本叠加,而不是重新覆盖,支持回滚与删除回复
    7. 通过标签系统,提供更灵活的配置项与客户端的匹配关系

    涉及方面

    有了大概的解决思路以后,可以对涉及到的方面进行整体盘点,其实这也是移动端基础设施的摸查,涉及以下几个方面:


    image
    • 客户端配置组件,与配置中心交互,获取配置信息,定时轮询更新策略,内存缓存与本地持久化配置信息,增量包应用,接收服务端推送事件
    • 配置中心,提供对客户端获取配置的API接口服务,接口支持根据客户端信息和标签返回增量数据包/全量更新包
    • 后台管理系统,提供应用管理和配置管理,支持新建配置,修改配置,回滚和删除配置
    • 认证服务,客户端通过认证服务以后,获取通讯管道加密的会话密钥,提供接口数据加密功能
    • 标签系统,提供对客户端、设备、用户等多个维度的标签设置和获取服务
    • 消息中心,提供根据标签系统,将配置更新的事件推送到客户端
    • 定时任务系统,提供定时服务,将配置生效、推送配置等设置为定时任务

    整体设计

    API设计

    客户端与配置中心进行API交互,接口定义如下:
    queryConfiguration
    入参:

    • clientInfo,包含appid、appVersion、platform、channel等
    • cacheInfo
    {
        "clientInfo":{
            "appid":"***",
            "appVersion":"1.0.0",
            "platform":"1", //1为iOS 2为Android
            "channel":"AppStore"
        },
        "cacheInfo":[{
                "configName":"routerConfigMap",
                "version":"*****"
            },
            {
                "configName":"conditionConfiguration",
                "version":"*****"
            }
        ]
    }
    

    返回值:

    • configurationData,一个数组,包含配置项全量或者增量数据包
    code 含义 备注
    0 增量包 返回增量包数据
    1 全量数据 返回配置全量数据
    2 已删除 表示该配置项已删除
    {
        configurationData:[
            {
                "configName":"routerConfigMap",
                "version":"*****",
                "code":0,
                  "hash":"*****",
                "patch":[]
            },
            {
                "configName":"orderActivity",
                "version":"xxxxxx",
                "code":1,
                  "hash":"*****",
                "value":"xxxxx"
            },
            {
                "configName":"conditionConfiguration",
                "version":"xxxxxx",
                "code":2
            },
        ]
    }
    

    客户端与API交互流程图


    image

    配置中心管理平台

    App管理平台

    image

    配置平台

    image image

    配置管理后台,提供对应用的管理与配置项的管理,配置项与基本客户端信息关联。
    配置项存储与客户端信息进行关联映射,关系有OR和AND两种,每个配置项设置关联条件。例如配置项的关联条件为:

    configId <—> appId AND appVersion AND channel AND platform OR tag

    image

    新建、更新或者删除某一配置,可以设置定时生效,Job系统会定时执行操作,并调用消息中心,按照关联条件,进行推送通知给客户端,客户端接到更新事件后,再调用API接口完成配置项更新。

    服务端查询配置项流程

    image

    这个流程里有三个关键点:

    1. 根据clientInfo查询匹配的配置列表,其中,AND关系和OR关系,需要通过构建一个配置id与条件的字典表,查询的时候将AND或者OR的条件相关的配置id全部查询出来,然后进行AND计算(取交集),OR计算取并集,其中appVersion是一个范围,例如设置某一配置项的appVersion为”<=2.3.0 & >=2.1.0”, 根据语义化版本,进行单独匹配,语义化版本 2.0.0 | Semantic Versioning的规范请详细查看文档
    2. 如果客户端上传有cacheInfo,将缓存的配置id列表上传,那么,根据条件查出的最新配置id列表为A,上传的缓存配置id列表为B,分别计算出A与B的交集,逐个对比hash值,算出增量包,再算出属于A但不属于B的部分,属于新增配置项,做全量包,再算出属于B不属于A的,属于要删除的部分。进行上述计算,只需要定义一套数组的交集、并集与补集的计算,就可计算出结果。
    3. 生成增量包的时候,需要根据客户端配置id和对应hash值,找到旧版本的配置项,再跟最新的配置项做文本对比生成增量包。文本增量算法有google官方实现的一套:GitHub - google/diff-match-patch: Diff Match Patch is a high-performance library in multiple languages that manipulates plain text.

    推送更新消息

    这个比较简单,通过后台增删改查的配置项,根据其标签和客户端信息,使用消息中心,将更新事件静默推送到设备,而设备客户端信息和标签,与设备唯一标示的绑定关系,在标签系统维护。

    总结改进

    新的配置中心,满足了现阶段的需求,通过将配置项的关联条件抽象成标签,再加上增量更新,满足了节省流量的需求。
    未来还有进一步改进的空间:

    1. 配置后台通过jsonschema来效验配置的格式,方式配置错误
    2. 客户端的配置组件改善通讯方式,使用推拉结合的方式,目前的推送基于消息中心,未来可以使用UDP+心跳方式维持客户端与服务端的数据同步
    3. 实现更多的更新发布场景,例如,更新配置项,可按照一定比例,逐步进行灰度更新,失败可回退,提高可用性

    多谢您花费宝贵的时间阅读,希望能够与大家多多交流

    相关文章

      网友评论

        本文标题:从移动端的配置说起

        本文链接:https://www.haomeiwen.com/subject/pauscqtx.html