关于系统设计:论配置化系统的配置

9次阅读

共计 2641 个字符,预计需要花费 7 分钟才能阅读完成。

形容

很多业务场景固定、不那么偏差 ” 业务 ” 的零碎如果遇到靠谱的工程师最终会走向配置化。达到配置化的先决条件是 零碎外部有个”引擎“模块,引擎读取配置信息把业务流程生成出执行打算,这个执行打算依据业务状态能够是 DAG、链表、树 或是其余。有了这套零碎,日常开发就变成写配置 + 丰盛零碎能力了。

举个之前文章提到的例子:

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

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

这整个流程齐全能够用配置化形式解决:

  1. MQ 音讯的 ETL 在配置中形容须要的字段的 path 信息解析;
  2. 黄色方块的 operator 次要操作存储,须要在配置中形容数据的存储以及获取相干的信息;
  3. 蓝色方块的 operator 是纯计算流程,配置中形容 schema 格局即可;

最初再配个转发 mq 音讯的配置,不到一小时反对了一个看起来有点简单的业务需要,此时你就能够美滋滋的写周报去了~

整个流程看起来无比丝滑,然而配置化零碎是银弹吗?持续探索一下所谓的”配置“。

咋存

第一个问题是零碎的配置存在哪里。

配置化零碎的实质是:引擎解析配置信息,生成 operator 执行打算操作 DB 和计算行为。程序员通过提前写好通用 operator,反对业务时不上线、不写定制代码,只写配置信息就能够反对业务,肯定水平上进步了开发效率。

配置信息能够抉择存到 db 或是 file 里。如果咱们目标之一是不上线即可反对业务,那把配置信息写到文件里就不是个好主见,因为在代码中更新文件后还得通过上线流程,这样会升高效率,所以把配置存到 db 里。

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

  1. 后面例子中讲到了完单量这个业务流程的配置信息,配置信息能够当成一个 API 供上游调用,这样的 API 是能够复用的,当零碎里有成千上万的 API 后,若没有一套管理系统来治理元信息,那简直就是劫难了。配置的元信息存到 MySQL 后,你能够很高兴的写一些治理接口治理配置。
  2. 基于 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 操作了。

对于配置自身,能够有一些形式来保障高可用,在零碎外部,同样能够做一些兜底操作,如下图所示:

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

正文完
 0