论配置化系统的配置
描述
咋存
咋配
咋保证HA
描述
很多业务场景固定、不那么偏向"业务"的系统如果遇到靠谱的工程师最终会走向配置化。达到配置化的先决条件是 系统内部有个”引擎“模块,引擎读取配置信息把业务流程生成出执行计划,这个执行计划根据业务形态可以是 DAG、链表、树 或是其他。有了这套系统,日常开发就变成写配置+丰富系统能力了。
举个之前文章提到的例子:
“用户每次下单后统计其当天完单量,并发给下游营销系统其总完单量信息。下游营销系统会根据用户的完单量推送优惠策略。
这个业务需求抽象后可以用下图表示业务流程,黄色方块主要和存储打交道,蓝色方块是纯计算流程。
这整个流程完全可以用配置化方式解决:
MQ消息的ETL在配置中描述需要的字段的path信息解析;
黄色方块的operator主要操作存储,需要在配置中描述数据的存储以及获取相关的信息;
蓝色方块的operator是纯计算流程,配置中描述schema格式即可;
最后再配个转发mq消息的配置,不到一小时支持了一个看起来有点复杂的业务需求,此时你就可以美滋滋的写周报去了~
整个流程看起来无比丝滑,但是配置化系统是银弹吗?继续探究一下所谓的”配置“。
咋存
第一个问题是系统的配置存在哪里。
配置化系统的本质是:引擎解析配置信息,生成operator执行计划操作DB和计算行为。程序员通过提前写好通用operator,支持业务时不上线、不写定制代码,只写配置信息就可以支持业务,一定程度上提高了开发效率。
配置信息可以选择存到db或是file里。如果我们目的之一是不上线即可支持业务,那把配置信息写到文件里就不是个好主意,因为在代码中更新文件后还得经过上线流程,这样会降低效率,所以把配置存到db里。
把配置文件存入像MySQL这样的db里,还有其他好处:
前面例子中讲到了完单量这个业务流程的配置信息,配置信息可以当成一个API供上游调用,这样的API是可以复用的,当系统里有成千上万的API后,若没有一套管理系统来管理元信息,那几乎就是灾难了。配置的元信息存到MySQL后,你可以很快乐的写一些管理接口管理配置。 基于MySQL的备份机制还可以做配置信息备份,以防不测。
咋配
第二个问题是 配置=简单吗?
有了配置化系统之后,开发日常的工作就变成了写配置,然而在mysql里通过SQL写配置并不一定比写代码轻松愉快...
文章前面的例子模型可以抽象成一个形如链表的pipline,这样看起来还比较简单,但是现实中很多业务比这个要复杂多了,很多业务抽象出来是个好几层的树型结构,这种东西靠人写SQL描述执行计划并不一定比写代码简单多少。稍微拓展一下上面的例子:
“用户每次完单后统计其总完单量,完单量达到不同阈值后给用户下发不同的成就。
这个API的模型如下图所示,它采用所谓的lambda架构,在离线中计算用户T+1的总单量,同时根据离线总单量产出日期dt 补充在线单量,最终把两部分数据加起来返回给业务方结果。
为啥要采用这样的架构呢。由于离线数据的产出时间不固定,所以需要一个dt字段做标识。
举个例子,现在是3月20号凌晨1点整,此时19号的离线任务没有跑完,此时单量计算规则为:
“用户总完单量 = 18号总单量(离线)+19号当天单量(在线) + 20号当天单量(在线)。
若现在8点钟,离线任务跑完了,此时单量计算规则为:
“用户总完单量 = 19号总单量(离线) + 20号当天单量(在线)。
上面这套流程已经比较复杂了,你可以想一下这块该如何配置,再想想如何通过SQL去描述配置。如果业务方还想在API中增加判定逻辑,比如 单量超过500单就通知下游给用户发个章,那配置起来就更复杂了。所以把配置存到管理平台后,还需要在平台上搞一个牛逼的前端页面,让开发同学可以在界面上勾勾选,拖拖拽拽,把配置描述出来,而且支持REPL让用户可以debug。
咋保证HA
现在有了管理系统+MySQL去管理配置就万事大吉了吗?
万事总有个意外。业务迭代过程中,系统开发一般会比平台开发先行。比如你为这套牛逼的配置系统增加了一个feature,在这个feature集成到平台之前,还是得写SQL做需求。这其实有很大风险的:如果你SQL写错了,在线下没复现出来,业务比较着急,上线时候没灰度就上全量集群了,系统就崩了~此时你慌得一批,赶紧写了个delete的SQL去删除那行配置,如果这个delete恰好没加条件,且你的MySQL中没配置SQL_SAFE_UPDATES
变量,那恭喜你,这一趟折腾下来系统不可用时间起码半个小时,可以准备跑路了~
前面那段是我编的,只是要说明需要保证配置的HA(high availability)。
我们写代码时会使用git来做版本控制,且像golang这种编译型语言还会有编译器来帮你检查代码是否有语法错误。如果配置也像代码一样,那该有多好啊:
实际上这两部分都是可以达到的,
编译检查方面:配置信息一般使用json格式表示,所谓编译检查一方面可以检查json格式是否正确,另一方面可以根据业务特性检查json配置是否符合规范。
版本控制方面:前些日子逛Github时我发现了一个有趣的库:https://github.com/dolthub/dolt。看一下它的介绍:
“Dolt is a SQL database that you can fork, clone, branch, merge, push and pull just like a git repository. Connect to Dolt just like any MySQL database to run queries or update the data using SQL commands. Use the command line interface to import CSV files, commit your changes, push them to a remote, or merge your teammate's changes.
这玩意可以视为一个支持SQL协议和Git协议的数据库,支持git就有趣多了,我们所有关于配置的更改记录都有版本信息,基于这个库封装出API并集成在管理平台中,前端渲染一个酷炫版本信息页面。我们就可以通过点点点进行git reset操作了。
对于配置本身,可以有一些方式来保证高可用,在系统内部,同样可以做一些兜底操作,如下图所示:
推荐阅读