不少業務場景固定、不那麼偏向"業務"的系統若是遇到靠譜的工程師最終會走向配置化。達到配置化的先決條件是 系統內部有個」引擎「模塊,引擎讀取配置信息把業務流程生成出執行計劃,這個執行計劃根據業務形態能夠是 DAG、鏈表、樹 或是其餘。有了這套系統,平常開發就變成寫配置+豐富系統能力了。前端
舉個以前文章提到的例子:mysql
用戶每次下單後統計其 當天完單量,併發給下游營銷系統其總完單量信息。下游營銷系統會根據用戶的完單量推送優惠策略。
這個業務需求抽象後能夠用下圖表示業務流程,黃色方塊主要和存儲打交道,藍色方塊是純計算流程。git
這整個流程徹底能夠用配置化方式解決:程序員
最後再配個轉發mq消息的配置,不到一小時支持了一個看起來有點複雜的業務需求,此時你就能夠美滋滋的寫週報去了~github
整個流程看起來無比絲滑,可是配置化系統是銀彈嗎?繼續探究一下所謂的」配置「。golang
第一個問題是系統的配置存在哪裏。sql
配置化系統的本質是:引擎解析配置信息,生成operator執行計劃操做DB和計算行爲。程序員經過提早寫好通用operator,支持業務時不上線、不寫定製代碼,只寫配置信息就能夠支持業務,必定程度上提升了開發效率。數據庫
配置信息能夠選擇存到db或是file裏。若是咱們目的之一是不上線便可支持業務,那把配置信息寫到文件裏就不是個好主意,由於在代碼中更新文件後還得通過上線流程,這樣會下降效率,因此把配置存到db裏。json
把配置文件存入像MySQL這樣的db裏,還有其餘好處:架構
第二個問題是 配置=簡單嗎?
有了配置化系統以後,開發平常的工做就變成了寫配置,然而在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。
如今有了管理系統+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]。