论配置化系统的配置

描述

不少业务场景固定、不那么偏向"业务"的系统若是遇到靠谱的工程师最终会走向配置化。达到配置化的先决条件是 系统内部有个”引擎“模块,引擎读取配置信息把业务流程生成出执行计划,这个执行计划根据业务形态能够是 DAG、链表、树 或是其余。有了这套系统,平常开发就变成写配置+丰富系统能力了。前端

举个以前文章提到的例子:mysql

用户每次下单后统计其 当天完单量,并发给下游营销系统其总完单量信息。下游营销系统会根据用户的完单量推送优惠策略。

这个业务需求抽象后能够用下图表示业务流程,黄色方块主要和存储打交道,蓝色方块是纯计算流程。git

image.png

这整个流程彻底能够用配置化方式解决:程序员

  1. MQ消息的ETL在配置中描述须要的字段的path信息解析;
  2. 黄色方块的operator主要操做存储,须要在配置中描述数据的存储以及获取相关的信息;
  3. 蓝色方块的operator是纯计算流程,配置中描述schema格式便可;

最后再配个转发mq消息的配置,不到一小时支持了一个看起来有点复杂的业务需求,此时你就能够美滋滋的写周报去了~github

整个流程看起来无比丝滑,可是配置化系统是银弹吗?继续探究一下所谓的”配置“。golang

咋存

第一个问题是系统的配置存在哪里。sql

配置化系统的本质是:引擎解析配置信息,生成operator执行计划操做DB和计算行为。程序员经过提早写好通用operator,支持业务时不上线、不写定制代码,只写配置信息就能够支持业务,必定程度上提升了开发效率。数据库

配置信息能够选择存到db或是file里。若是咱们目的之一是不上线便可支持业务,那把配置信息写到文件里就不是个好主意,由于在代码中更新文件后还得通过上线流程,这样会下降效率,因此把配置存到db里。json

把配置文件存入像MySQL这样的db里,还有其余好处:架构

  1. 前面例子中讲到了完单量这个业务流程的配置信息,配置信息能够当成一个API供上游调用,这样的API是能够复用的,当系统里有成千上万的API后,若没有一套管理系统来管理元信息,那几乎就是灾难了。 配置的元信息存到MySQL后,你能够很快乐的写一些管理接口管理配置。
  2. 基于MySQL的备份机制还能够作配置信息备份,以防不测。

咋配

第二个问题是 配置=简单吗?

有了配置化系统以后,开发平常的工做就变成了写配置,然而在mysql里经过SQL写配置并不必定比写代码轻松愉快...

文章前面的例子模型能够抽象成一个形如链表的pipline,这样看起来还比较简单,可是现实中不少业务比这个要复杂多了,不少业务抽象出来是个好几层的树型结构,这种东西靠人写SQL描述执行计划并不必定比写代码简单多少。稍微拓展一下上面的例子:

用户每次完单后统计其 完单量,完单量达到不一样阈值后给用户下发不一样的 成就

这个API的模型就变以下图所示,它采用所谓的lambda架构,在离线中计算用户T+1的总单量,同时根据离线总单量产出日期dt 补充在线单量,最终把两部分数据加起来返回给业务方结果。

image.png

为啥要采用这样的架构呢。因为离线数据的产出时间不固定,因此须要一个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这种编译型语言还会有编译器来帮你检查代码是否有语法错误。若是配置也像代码同样,那该有多好啊:

image.png

实际上这两部分都是能够达到的,

编译检查反面:配置信息通常使用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操做了。

对于配置自己,能够有一些方式来保证高可用,在系统内部,一样能够作一些兜底操做,以下图所示:

image.png

在系统中引入一个双buffer去读取配置。系统正常读取cache[0],用户更改配置后从db中读取新的配置入cache[1],若是此时出现异常,能够写接口让系统回滚读取cache[0]。

相关文章
相关标签/搜索