自動(dòng)化微服務(wù)治理
關(guān)于『設(shè)計(jì)一個(gè)微服務(wù)治理的工具』這個(gè)想法,我已經(jīng)醞釀很久了。但是,你懂的,又是因?yàn)榉N種原因,我擱置了蠻久了。最近,剛好因?yàn)樵谘芯俊杭軜?gòu)適應(yīng)度函數(shù)』,所以,我有了一個(gè)新的想法。微服務(wù)架構(gòu)治理,看似和架構(gòu)適應(yīng)度函數(shù)并沒(méi)有啥關(guān)系。但是,我設(shè)想的是一個(gè)用于『微服務(wù)治理的架構(gòu)適應(yīng)度函數(shù)』。
你可以把它想象為一個(gè)用于幫助更好開(kāi)發(fā)微服務(wù)應(yīng)用的工具。順便一提,因?yàn)槭诸^上并沒(méi)有這樣的場(chǎng)景。所以,我先把我的相關(guān)思路記載下來(lái),方便于后續(xù)集成。而且大部分功能已經(jīng)在 Coca 中實(shí)現(xiàn),我會(huì)將部分的功能再交由 Coca 來(lái)實(shí)現(xiàn)。如對(duì)于,數(shù)據(jù)庫(kù)的自動(dòng)化分析 —— 已經(jīng)有 Tequila 進(jìn)行了大量的自動(dòng)化。
微服務(wù)粒度適應(yīng)度函數(shù)
對(duì)于微服務(wù)架構(gòu)來(lái)說(shuō),最令人頭疼的一個(gè)問(wèn)題就是微服務(wù)粒度。從最源頭上,我們應(yīng)該遵循『兩個(gè)披薩團(tuán)隊(duì)』這個(gè)定律,即:
單個(gè)服務(wù)的設(shè)計(jì),所有參與人從設(shè)計(jì)、開(kāi)發(fā)、測(cè)試、運(yùn)維所有人加起來(lái) 只需要 2 個(gè)披薩就夠了。
但是,事實(shí)上從國(guó)內(nèi)大中小公司的實(shí)踐情況來(lái)看,并非如此。往往是一個(gè)團(tuán)隊(duì)維護(hù)了超過(guò)其自身數(shù)量的微服務(wù),即 6 個(gè)開(kāi)發(fā)人員可能維護(hù)了 8 個(gè)微服務(wù)。大家常犯的一個(gè)錯(cuò)誤是:通過(guò)技術(shù)維度而非業(yè)務(wù)維度劃分微服務(wù)。關(guān)于這部分的自動(dòng)化,我暫時(shí)找不到頭緒。但是,我們可以判斷兩個(gè)微服務(wù)是否可以合并:即基于 Git 日志的微服務(wù)粒度合理性分析。
- 服務(wù)提交人數(shù)。通過(guò) git log 來(lái)查看單個(gè)微服務(wù)的提交情況
- 變更頻率。尋找多個(gè)模塊之間,是否存在大量同時(shí)變更的情況
- 需求關(guān)聯(lián)度。通過(guò)識(shí)別提交信息規(guī)范,來(lái)識(shí)別多個(gè)微服務(wù)、模塊、類是否存在經(jīng)常同時(shí)變更
- 前提:匹配提交規(guī)范。
在這個(gè)時(shí)候,我們只需要使用和 coca git 類似的解析函數(shù),就能達(dá)到類似的效果。
API 的適應(yīng)度函數(shù)
在 Coca 中已經(jīng)內(nèi)置了 API 分析相關(guān)的功能,可以支持識(shí)別 Spring 的 API 注解,以及服務(wù)聲明的 API 方式,同時(shí)分析調(diào)用關(guān)系等等。所以,我就不需要開(kāi)發(fā)一個(gè)這樣的功能了,只需要稍微完善一下,補(bǔ)充一些分值情況。對(duì)于 API 設(shè)計(jì)來(lái)說(shuō),這個(gè)工具要做這么幾件事:
- API 命名的規(guī)范。如不一致的命名方式
- 參數(shù)合理性。如過(guò)多或者過(guò)少、是否不應(yīng)該出現(xiàn)在 URL 中。
- 是否符合 RESTful 規(guī)范。如 URL 中不應(yīng)該出現(xiàn) get 和 post 等字眼,是否所有的 API 都是 post。
- 是否出現(xiàn)跨服務(wù)使用相同的資源前綴。
對(duì)于大部分的公司來(lái)說(shuō),要做到 RESTful 的第一級(jí)都相當(dāng)?shù)睦щy。
數(shù)據(jù)庫(kù)表適應(yīng)度函數(shù)
微服務(wù)把服務(wù)間調(diào)用從函數(shù)調(diào)用變成了遠(yuǎn)程調(diào)用,這也意味著,我們并不能從 A 服務(wù)直接訪問(wèn) B 服務(wù)的數(shù)據(jù)庫(kù),而是通過(guò)訪問(wèn) B 服務(wù)的接口,借助它去訪問(wèn)數(shù)據(jù)庫(kù)。但是,在某些場(chǎng)景下,A 和 B 是需要共用數(shù)據(jù)庫(kù)(比如說(shuō),收費(fèi)的 Oracle 數(shù)據(jù)庫(kù)實(shí)例),但是我們需要強(qiáng)制性的限制 A 和 B 服務(wù)對(duì)于表的訪問(wèn)。所以,我們需要分析多個(gè)服務(wù)之間是否存在對(duì)于同一個(gè)表的修改,又或者是存在對(duì)于多個(gè)表的修改。
- 表和服務(wù)關(guān)系維護(hù)。掃描 MyBatis 等這一類的工具,生成表和服務(wù)關(guān)系維護(hù)
- 實(shí)現(xiàn)『數(shù)據(jù)庫(kù)表-映射服務(wù)』的快照測(cè)試。
簡(jiǎn)單來(lái)說(shuō),我們的工具在這一部分所要做的事情是:每次代碼提交時(shí),進(jìn)行自動(dòng)化地掃描,生成一個(gè)快照。剛其與存儲(chǔ)的快照進(jìn)行對(duì)比,判斷數(shù)據(jù)庫(kù)是否有問(wèn)題。隨后設(shè)置一個(gè)合理的調(diào)優(yōu)公式,也就是這部分的架構(gòu)適應(yīng)度函數(shù)。
分層架構(gòu)適應(yīng)度函數(shù)
在解決了表面的問(wèn)題之后,我們可以嘗試達(dá)到整潔架構(gòu)這一目的。對(duì)于分層架構(gòu)來(lái)說(shuō),我們要做的事情可能會(huì)稍微復(fù)雜一下。不過(guò),好在復(fù)雜的調(diào)用關(guān)系識(shí)別,已經(jīng)由 Coca 實(shí)現(xiàn)了。于是乎,對(duì)于我們的分層架構(gòu)適應(yīng)度函數(shù),只需要做到這么一些事情:
微服務(wù)之間是否存在函數(shù)調(diào)用?
- 單個(gè)服務(wù)的所有 API 是否在同一個(gè)包內(nèi),如 controller。
- 是否存在不合理的 common、util 模塊。
- 對(duì)于三層包架構(gòu)遷移到整潔架構(gòu)的改進(jìn)可視化。
- 簡(jiǎn)單來(lái)說(shuō),就是將《系統(tǒng)重構(gòu)與遷移指南》一書中記載的部分,通過(guò)自動(dòng)化的方式進(jìn)行識(shí)別。
數(shù)據(jù)結(jié)構(gòu)適應(yīng)度函數(shù)
關(guān)于數(shù)據(jù)結(jié)構(gòu)/數(shù)據(jù)模型,已經(jīng)有一些工具可以做類似的事情。對(duì)于微服務(wù)架構(gòu)來(lái)說(shuō),我們所要做的一些判斷是:
- 不合理的耦合。如果一個(gè)結(jié)構(gòu)體/類同時(shí)被大量的其它類調(diào)用,必然有一定的不合理之處。
- 過(guò)大的模型。值得注意的是,在一些大數(shù)據(jù)的場(chǎng)景下,這個(gè)反而是正確的
- 過(guò)于復(fù)雜的嵌套。
- 沒(méi)有行為的模型。
然后,針對(duì)于一些不同的使用情況,還存在一些不一樣的識(shí)別模式。
模型分析
在某些特定的場(chǎng)景之下,團(tuán)隊(duì)會(huì)將共用的模型抽取到公共的模塊中,提供給多個(gè)微服務(wù)使用。這種模式本身可能是有問(wèn)題的,因?yàn)樵诓煌南藿缟舷挛睦铮┠P捅旧聿粦?yīng)該是一致的。
相似度分析
考慮到復(fù)用和耦合之間的關(guān)系,這里不會(huì)建議它們共用的。不同服務(wù)之間需要一定的 copy/paste,但是需要考慮更好的方式,如采用類似于 proto 這樣的 DSL 生成方式。同時(shí),通過(guò) DDD 的方式進(jìn)行管理 —— 針對(duì)于不同的相似類型,有更好的命名方式。
其它細(xì)節(jié)
我們還要做好一些基礎(chǔ)設(shè)施,比如對(duì)于模塊的處理:
模塊標(biāo)志
- build.xml
- gradle
- pom.xml
- bazel
- 模塊歸屬權(quán)
- 需求關(guān)聯(lián)
- 提交信息識(shí)別(可輸入式正則關(guān)系,配置化)
- 記錄包-需求-服務(wù)關(guān)系
- 聚類分析
- ……
嗯,這些都不是容易的事。
結(jié)論
你的微服務(wù)架構(gòu)適應(yīng)度函數(shù)呢?
本文轉(zhuǎn)載自微信公眾號(hào)「phodal」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系phodal公眾號(hào)。