怎樣才算是架構(gòu)師?
架構(gòu)師是一個(gè)既能掌控整體又能洞悉局部瓶頸并依據(jù)具體的業(yè)務(wù)場(chǎng)景給出解決方案的團(tuán)隊(duì)領(lǐng)導(dǎo)型人物??此仆昝赖?ldquo;人格模型”背后,是艱辛的探索。
架構(gòu)師不是一個(gè)人,他需要建立高效卓越的體系,帶領(lǐng)團(tuán)隊(duì)去攻城略地,在規(guī)定的時(shí)間內(nèi)完成項(xiàng)目。
架構(gòu)師的分類
從業(yè)界來(lái)看對(duì)于架構(gòu)師的理解可以大概區(qū)分為:
企業(yè)架構(gòu)師:專注于企業(yè)總體 IT 架構(gòu)的設(shè)計(jì)。
IT 架構(gòu)師-軟件產(chǎn)品架構(gòu)師:專注于軟件產(chǎn)品的研發(fā)。
IT 架構(gòu)師-應(yīng)用架構(gòu)師:專注于結(jié)合企業(yè)需求,定制化 IT 解決方案;大部分需要交付的工作包括總體架構(gòu)、應(yīng)用架構(gòu)、數(shù)據(jù)架構(gòu),甚至部署架構(gòu)。
IT 架構(gòu)師-技術(shù)架構(gòu)師:專注于基礎(chǔ)設(shè)施,某種軟硬件體系,甚至云平臺(tái),提交:產(chǎn)品建議、產(chǎn)品選型、部署架構(gòu)、網(wǎng)絡(luò)方案,甚至數(shù)據(jù)中心建設(shè)方案等。
架構(gòu)師的職責(zé)
架構(gòu)師需要能夠識(shí)別定義并確認(rèn)需求,能夠進(jìn)行系統(tǒng)分解形成整體架構(gòu),能夠正確地技術(shù)選型,能夠制定技術(shù)規(guī)格說(shuō)明并有效推動(dòng)實(shí)施落地。
按 TOGAF 的定義,架構(gòu)師的職責(zé)是了解并關(guān)注實(shí)際上關(guān)系重大但未變得過(guò)載的一些關(guān)鍵細(xì)節(jié)和界面,架構(gòu)師的角色有:理解并解析需求,創(chuàng)建有用的模型,確認(rèn)、細(xì)化并擴(kuò)展模型,管理架構(gòu)。
從項(xiàng)目視圖看:
- 對(duì)接管理部門:匯報(bào)技術(shù)方案,進(jìn)度;技術(shù)溝通;
- 對(duì)接客戶 PM,項(xiàng)目 PM:協(xié)助項(xiàng)目計(jì)劃,人員管理等。負(fù)責(zé)所有技術(shù)交付物的指導(dǎo);
- 對(duì)接業(yè)務(wù)部門和需求人員:了解和挖掘痛點(diǎn),幫忙梳理高級(jí)業(yè)務(wù)需求,指導(dǎo)需求工藝;
- 對(duì)接開(kāi)發(fā):產(chǎn)品支持、技術(shù)指導(dǎo)、架構(gòu)指導(dǎo);
- 對(duì)接測(cè)試:配合測(cè)試計(jì)劃和工藝制定。配合性能測(cè)試或者非功能性測(cè)試;
- 對(duì)接運(yùn)維:產(chǎn)品支持,運(yùn)維支持;
- 對(duì)接配置&環(huán)境:產(chǎn)品支持;
.......
架構(gòu)原則
設(shè)計(jì)原則就是架構(gòu)設(shè)計(jì)的指導(dǎo)思想,它指導(dǎo)我們?nèi)绾螌?shù)據(jù)和函數(shù)組織成類,如何將類鏈接起來(lái)成為組件和程序。反向來(lái)說(shuō),架構(gòu)的主要工作就是將軟件拆解為組件,設(shè)計(jì)原則指導(dǎo)我們?nèi)绾尾鸾?、拆解的粒度、組件間依賴的方向、組件解耦的方式等。
設(shè)計(jì)原則有很多,我們進(jìn)行架構(gòu)設(shè)計(jì)的主導(dǎo)原則是 OCP(開(kāi)閉原則),在類和代碼的層級(jí)上有:SRP(單一職責(zé)原則)、LSP(里氏替換原則)、ISP(接口隔離原則)、DIP(依賴反轉(zhuǎn)原則);在組件的層級(jí)上有:REP(復(fù)用、發(fā)布等同原則)、CCP(共同閉包原則)、CRP(共同復(fù)用原則),處理組件依賴問(wèn)題的三原則:無(wú)依賴環(huán)原則、穩(wěn)定依賴原則、穩(wěn)定抽象原則。
設(shè)計(jì)原則
1、OCP(開(kāi)閉原則):設(shè)計(jì)良好的軟件應(yīng)該易于擴(kuò)展,同時(shí)抗拒修改。這是我們進(jìn)行架構(gòu)設(shè)計(jì)的主導(dǎo)原則,其他的原則都為這條原則服務(wù)。
2、SRP(單一職責(zé)原則):任何一個(gè)軟件模塊,都應(yīng)該有且只有一個(gè)被修改的原因,“被修改的原因“指系統(tǒng)的用戶或所有者,翻譯一下就是,任何模塊只對(duì)一個(gè)用戶的價(jià)值負(fù)責(zé),該原則指導(dǎo)我們?nèi)绾尾鸱纸M件。
舉個(gè)例子,CTO 和 COO 都要統(tǒng)計(jì)員工的工時(shí),當(dāng)前他們要求的統(tǒng)計(jì)方式可能是相同的,我們復(fù)用一套代碼,這時(shí) COO 說(shuō)周末的工時(shí)統(tǒng)計(jì)要乘以二,按照這個(gè)需求修改完代碼,CTO 可能就要過(guò)來(lái)罵街了。當(dāng)然這是個(gè)非常淺顯的例子,實(shí)際項(xiàng)目中也有很多代碼服務(wù)于多個(gè)價(jià)值主體,這帶來(lái)很大的探秘成本和修改風(fēng)險(xiǎn),另外,當(dāng)一份代碼有多個(gè)所有者時(shí),就會(huì)產(chǎn)生代碼合并沖突的問(wèn)題。
3、LSP(里氏替換原則):當(dāng)用同一接口的不同實(shí)現(xiàn)互相替換時(shí),系統(tǒng)的行為應(yīng)該保持不變。該原則指導(dǎo)的是接口與其實(shí)現(xiàn)方式。
你一定很疑惑,實(shí)現(xiàn)了同一個(gè)接口,他們的行為也肯定是一致的呀,還真不一定。假設(shè)認(rèn)為矩形的系統(tǒng)行為是:面積=寬*高,讓正方形實(shí)現(xiàn)矩形的接口,在調(diào)用 setW 和 setH 時(shí),正方形做的其實(shí)是同一個(gè)事情,設(shè)置它的邊長(zhǎng)。這時(shí)下邊的單元測(cè)試用矩形能通過(guò),用正方形就不行,實(shí)現(xiàn)同樣的接口,但是系統(tǒng)行為變了,這是違反 LSP 的經(jīng)典案例。
Rectangle r = ... r.setW(5); r.setH(2); assert(r.area() == 10);
4、ISP(接口隔離原則):不依賴任何不需要的方法、類或組件。該原則指導(dǎo)我們的接口設(shè)計(jì)。當(dāng)我們依賴一個(gè)接口但只用到了其中的部分方法時(shí),其實(shí)我們已經(jīng)依賴了不需要的方法或類,當(dāng)這些方法或類有變更時(shí),會(huì)引起我們類的重新編譯,或者引起我們組件的重新部署,這些都是不必要的。所以我們最好定義個(gè)小接口,把用到的方法拆出來(lái)。
5、DIP(依賴反轉(zhuǎn)原則):指一種特定的解耦(傳統(tǒng)的依賴關(guān)系創(chuàng)建在高層次上,而具體的策略設(shè)置則應(yīng)用在低層次的模塊上)形式,使得高層次的模塊不依賴于低層次的模塊的實(shí)現(xiàn)細(xì)節(jié),依賴關(guān)系被顛倒(反轉(zhuǎn)),從而使得低層次模塊依賴于高層次模塊的需求抽象。
跨越組建邊界的依賴方向永遠(yuǎn)與控制流的方向相反。該原則指導(dǎo)我們?cè)O(shè)計(jì)組件間依賴的方向。
依賴反轉(zhuǎn)原則是個(gè)可操作性非常強(qiáng)的原則,當(dāng)你要修改組件間的依賴方向時(shí),將需要進(jìn)行組件間通信的類抽象為接口,接口放在邊界的哪邊,依賴就指向哪邊。
6、REP(復(fù)用、發(fā)布等同原則):軟件復(fù)用的最小粒度應(yīng)等同于其發(fā)布的最小粒度。直白地說(shuō),就是要復(fù)用一段代碼就把它抽成組件,該原則指導(dǎo)我們組件拆分的粒度。
7、CCP(共同閉包原則):為了相同目的而同時(shí)修改的類,應(yīng)該放在同一個(gè)組件中。CCP 原則是 SRP 原則在組件層面的描述。該原則指導(dǎo)我們組件拆分的粒度。
對(duì)大部分應(yīng)用程序而言,可維護(hù)性的重要性遠(yuǎn)遠(yuǎn)大于可復(fù)用性,由同一個(gè)原因引起的代碼修改,最好在同一個(gè)組件中,如果分散在多個(gè)組件中,那么開(kāi)發(fā)、提交、部署的成本都會(huì)上升。
8、CRP(共同復(fù)用原則):不要強(qiáng)迫一個(gè)組件依賴它不需要的東西。CRP 原則是 ISP原則在組件層面的描述。該原則指導(dǎo)我們組件拆分的粒度。
相信你一定有這種經(jīng)歷,集成了組件 A,但組件 A 依賴了組件 B、C。即使組件 B、C 你完全用不到,也不得不集成進(jìn)來(lái)。這是因?yàn)槟阒挥玫搅私M件 A 的部分能力,組件 A 中額外的能力帶來(lái)了額外的依賴。如果遵循共同復(fù)用原則,你需要把 A 拆分,只保留你要用的部分。
REP、CCP、CRP 三個(gè)原則之間存在彼此競(jìng)爭(zhēng)的關(guān)系,REP 和 CCP 是黏合性原則,它們會(huì)讓組件變得更大,而 CRP 原則是排除性原則,它會(huì)讓組件變小。遵守REP、CCP 而忽略 CRP,就會(huì)依賴了太多沒(méi)有用到的組件和類,而這些組件或類的變動(dòng)會(huì)導(dǎo)致你自己的組件進(jìn)行太多不必要的發(fā)布;遵守 REP、CRP 而忽略 CCP,因?yàn)榻M件拆分的太細(xì)了,一個(gè)需求變更可能要改 n 個(gè)組件,帶來(lái)的成本也是巨大的。
指導(dǎo)原則
除了上述設(shè)計(jì)原則,還有一些重要的指導(dǎo)原則如下:

1、N+1設(shè)計(jì):系統(tǒng)中的每個(gè)組件都應(yīng)做到?jīng)]有單點(diǎn)故障;
2、回滾設(shè)計(jì):確保系統(tǒng)可以向前兼容,在系統(tǒng)升級(jí)時(shí)應(yīng)能有辦法回滾版本;
3、禁用設(shè)計(jì):應(yīng)該提供控制具體功能是否可用的配置,在系統(tǒng)出現(xiàn)故障時(shí)能夠快速下線功能;
4、監(jiān)控設(shè)計(jì):在設(shè)計(jì)階段就要考慮監(jiān)控的手段,便于有效的排查問(wèn)題,比如引入traceId、業(yè)務(wù)身份 Id 便于排查監(jiān)控問(wèn)題;
5、多活數(shù)據(jù)中心設(shè)計(jì):若系統(tǒng)需要極高的高可用,應(yīng)考慮在多地實(shí)施數(shù)據(jù)中心進(jìn)行多活,至少在一個(gè)機(jī)房斷電的情況下系統(tǒng)依然可用;
6、采用成熟的技術(shù):剛開(kāi)發(fā)的或開(kāi)源的技術(shù)往往存在很多隱藏的 bug,出了問(wèn)題沒(méi)有很好的商業(yè)支持可能會(huì)是一個(gè)災(zāi)難;
7、資源隔離設(shè)計(jì):應(yīng)避免單一業(yè)務(wù)占用全部資源;
8、架構(gòu)水平擴(kuò)展設(shè)計(jì):系統(tǒng)只有做到能水平擴(kuò)展,才能有效避免瓶頸問(wèn)題;
9、非核心則購(gòu)買的原則:非核心功能若需要占用大量的研發(fā)資源才能解決,則考慮購(gòu)買成熟的產(chǎn)品;
10、使用商用硬件:商用硬件能有效降低硬件故障的機(jī)率;
11、快速迭代:系統(tǒng)應(yīng)該快速開(kāi)發(fā)小功能模塊,盡快上線進(jìn)行驗(yàn)證,早日發(fā)現(xiàn)問(wèn)題大大降低系統(tǒng)交付的風(fēng)險(xiǎn);
12、無(wú)狀態(tài)設(shè)計(jì):服務(wù)接口應(yīng)該做成無(wú)狀態(tài)的,當(dāng)前接口的訪問(wèn)不依賴于接口上次訪問(wèn)的狀態(tài)。
架構(gòu)師知道了職責(zé),具備很好的架構(gòu)思維,掌握了通用的架構(gòu)框架和方法論,使用架構(gòu)原則進(jìn)行架構(gòu)設(shè)計(jì),不同的業(yè)務(wù)和系統(tǒng)要求不一樣,那么有沒(méi)有針對(duì)不同場(chǎng)景的系統(tǒng)架構(gòu)設(shè)計(jì)?下文就針對(duì)分布式架構(gòu)演進(jìn)、單元化架構(gòu)、面向服務(wù) SOA 架構(gòu)、微服務(wù)架構(gòu)、Serverless 架構(gòu)進(jìn)行介紹,以便于我們?cè)趯?shí)際運(yùn)用中進(jìn)行參考使用。
具備架構(gòu)師的思維
架構(gòu)師職責(zé)明確了,那么有什么架構(gòu)思維可以指導(dǎo)架構(gòu)設(shè)計(jì)呢?請(qǐng)看下述的架構(gòu)思維。
1、自頂向下構(gòu)建架構(gòu)

要點(diǎn)主要如下:
1)首先定義問(wèn)題,而定義問(wèn)題中最重要的是定義客戶的問(wèn)題。定義問(wèn)題,特別是識(shí)別出關(guān)鍵問(wèn)題,關(guān)鍵問(wèn)題是對(duì)客戶有體感,能夠解決客戶痛點(diǎn),通過(guò)一定的數(shù)據(jù)化來(lái)衡量識(shí)別出來(lái),關(guān)鍵問(wèn)題要優(yōu)先給出解決方案。
2)問(wèn)題定義務(wù)必加入時(shí)間維度,把手段/方案和問(wèn)題定義區(qū)分開(kāi)來(lái)。
3)問(wèn)題定義中,需要對(duì)問(wèn)題進(jìn)行升層思考后再進(jìn)行升維思考,從而真正抓到問(wèn)題的本質(zhì),理清和挖掘清楚需求;要善用第一性原理思維進(jìn)行分析思考問(wèn)題。
4)問(wèn)題解決原則:先解決客戶的問(wèn)題(使命),然后才能解決自己的問(wèn)題(愿景);務(wù)必記住不是強(qiáng)調(diào)我們?cè)趺礃樱俏覀兡転榭蛻艟唧w解決什么問(wèn)題,然后才是我們變成什么,從而怎么樣去更好得服務(wù)客戶。
5)善用多種方法對(duì)客戶問(wèn)題進(jìn)行分析,轉(zhuǎn)換成我們產(chǎn)品或者平臺(tái)需要提供的能力,比如倉(cāng)儲(chǔ)系統(tǒng) WMS 可以提供哪些商業(yè)能力。
6)對(duì)我們的現(xiàn)有的流程和能力模型進(jìn)行梳理,找到需要提升的地方,升層思考和升維思考真正明確提升部分。
7)定義指標(biāo),并能夠?qū)χ笜?biāo)進(jìn)行拆解,然后進(jìn)行數(shù)學(xué)建模。
8)將抽象出來(lái)的能力訴求轉(zhuǎn)換成技術(shù)挑戰(zhàn),此步對(duì)于技術(shù)人員來(lái)說(shuō)相當(dāng)于找到了靶子,可以進(jìn)行方案的設(shè)計(jì)了,需要結(jié)合自底向上的架構(gòu)推導(dǎo)方式。
9)創(chuàng)新可以是業(yè)務(wù)創(chuàng)新,也可以是產(chǎn)品創(chuàng)新,也可以是技術(shù)創(chuàng)新,也可以是運(yùn)營(yíng)創(chuàng)新,升層思考、升維思考,使用第一性原理思維、生物學(xué)(進(jìn)化論--進(jìn)化=變異+選擇+隔離、熵增定律、分形和涌現(xiàn))思維等哲科思維可以幫助我們?cè)跇I(yè)務(wù),產(chǎn)品,技術(shù)上發(fā)現(xiàn)不同的創(chuàng)新可能。可以說(shuō)哲科思維是架構(gòu)師的靈魂思維。
2、自底向上推導(dǎo)應(yīng)用架構(gòu)

先根據(jù)業(yè)務(wù)流程,分解出系統(tǒng)時(shí)序圖,根據(jù)時(shí)序圖開(kāi)始對(duì)模塊進(jìn)行歸納,從而得到粒度更大的模塊,模塊的組合/聚合構(gòu)建整個(gè)系統(tǒng)架構(gòu)。
基本上應(yīng)用邏輯架構(gòu)的推導(dǎo)有4個(gè)子路徑,他們分別是:
- 業(yè)務(wù)概念架構(gòu):業(yè)務(wù)概念架構(gòu)來(lái)自于業(yè)務(wù)概念模型和業(yè)務(wù)流程;
- 系統(tǒng)模型:來(lái)自于業(yè)務(wù)概念模型;
- 系統(tǒng)流程:來(lái)自業(yè)務(wù)流程;
- 非功能性的系統(tǒng)支撐:來(lái)自對(duì)性能、穩(wěn)定性、成本的需要。
效率、穩(wěn)定性、性能是最影響邏輯架構(gòu)落地成物理架構(gòu)的三大主要因素,所以從邏輯架構(gòu)到物理架構(gòu),一定需要先對(duì)效率、穩(wěn)定性和性能做出明確的量化要求。
自底向上重度依賴于演繹和歸納。
如果是產(chǎn)品方案已經(jīng)明確,程序員需要理解這個(gè)業(yè)務(wù)需求,并根據(jù)產(chǎn)品方案推導(dǎo)出架構(gòu),此時(shí)一般使用自底向上的方法,而領(lǐng)域建模就是這種自底向上的分析方法。
對(duì)于自底向上的分析方法,如果提煉一下關(guān)鍵詞,會(huì)得到如下兩個(gè)關(guān)鍵詞:
1)演繹:演繹就是邏輯推導(dǎo),越是底層的,越需要演繹:
- 從用例到業(yè)務(wù)模型就屬于演繹;
- 從業(yè)務(wù)模型到系統(tǒng)模型也屬于演繹;
- 根據(jù)目前的問(wèn)題,推導(dǎo)出要實(shí)施某種穩(wěn)定性措施,這是也是演繹。
2)歸納:這里的歸納是根據(jù)事物的某個(gè)維度來(lái)進(jìn)行歸類,越是高層的,越需要?dú)w納:
- 問(wèn)題空間模塊劃分屬于歸納;
- 邏輯架構(gòu)中有部分也屬于歸納;
- 根據(jù)一堆穩(wěn)定性問(wèn)題,歸納出,事前,事中,事后都需要做對(duì)應(yīng)的操作,是就是根據(jù)時(shí)間維度來(lái)進(jìn)行歸納。
3、領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)架構(gòu)
大部分傳統(tǒng)架構(gòu)都是基于領(lǐng)域模型分析架構(gòu),典型的領(lǐng)域?qū)崿F(xiàn)模型設(shè)計(jì)可以參考DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)),詳細(xì)可以參考《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》這本書,另外《UML和模式應(yīng)用》在領(lǐng)域建模實(shí)操方面比較好,前者偏理論了解,后者便于落地實(shí)踐。
領(lǐng)域劃分設(shè)計(jì)步驟:
(1) 對(duì)用戶需求場(chǎng)景分析,識(shí)別出業(yè)務(wù)全維度 Use Case。
(2) 分析模型魯棒圖,識(shí)別出業(yè)務(wù)場(chǎng)景中所有的實(shí)體對(duì)象。魯棒圖 —— 是需求設(shè)計(jì)過(guò)程中使用的一種方法(魯棒性分析),通過(guò)魯棒分析法可以讓設(shè)計(jì)人員更清晰,更全面地了解需求。它通常使用在需求分析后及需求設(shè)計(jì)前做軟件架構(gòu)分析之用,它主要注重于功能需求的設(shè)計(jì)分析工作。需求規(guī)格說(shuō)明書為其輸入信息,設(shè)計(jì)模型為其輸出信息。它是從功能需求向設(shè)計(jì)方案過(guò)渡的第一步,重點(diǎn)是識(shí)別組成軟件系統(tǒng)的高級(jí)職責(zé)模塊、規(guī)劃模塊之間的關(guān)系。魯棒圖包含三種圖形:邊界、控制、實(shí)體,三個(gè)圖形如下:
(3) 領(lǐng)域劃分,將所有識(shí)別出的實(shí)體對(duì)象進(jìn)行分類。
(4) 評(píng)估域劃分合理性,并進(jìn)行優(yōu)化。
4、基于數(shù)據(jù)驅(qū)動(dòng)設(shè)計(jì)架構(gòu)
隨著 IoT、大數(shù)據(jù)和人工智能的發(fā)展,以領(lǐng)域驅(qū)動(dòng)的方式進(jìn)行架構(gòu)往往滿足不了需求或者達(dá)不到預(yù)期的效果,在大數(shù)據(jù)時(shí)代,在大數(shù)據(jù)應(yīng)用場(chǎng)景,我們需要轉(zhuǎn)變思維,從領(lǐng)域分析升維到基于大數(shù)據(jù)統(tǒng)計(jì)分析結(jié)果來(lái)進(jìn)行業(yè)務(wù)架構(gòu)、應(yīng)用架構(gòu)、數(shù)據(jù)架構(gòu)和技術(shù)架構(gòu)。這里需要架構(gòu)師具備數(shù)理統(tǒng)計(jì)分析的基礎(chǔ)和 BI 的能力,以數(shù)據(jù)思維來(lái)架構(gòu)系統(tǒng),典型的系統(tǒng)像阿里的數(shù)據(jù)分析平臺(tái)采云間和菜鳥的數(shù)據(jù)分析平臺(tái) FBI。
上述四種思維,往往在架構(gòu)設(shè)計(jì)中是融合使用的,需要根據(jù)業(yè)務(wù)或者系統(tǒng)的需求來(lái)選擇側(cè)重思維方式。
單元化架構(gòu),微服務(wù)架構(gòu)以及 Serveless 架構(gòu)
單元化架構(gòu)
1. 單元化是什么
單元化架構(gòu)是從并行計(jì)算領(lǐng)域發(fā)展而來(lái)。在分布式服務(wù)設(shè)計(jì)領(lǐng)域,一個(gè)單元(Cell)就是滿足某個(gè)分區(qū)所有業(yè)務(wù)操作的自包含的安裝。而一個(gè)分區(qū)(Shard),則是整體數(shù)據(jù)集的一個(gè)子集,如果你用尾號(hào)來(lái)劃分用戶,那同樣尾號(hào)的那部分用戶就可以認(rèn)為是一個(gè)分區(qū)。單元化就是將一個(gè)服務(wù)設(shè)計(jì)改造讓其符合單元特征的過(guò)程。

單元化架構(gòu),為什么要用以及我們?nèi)绾巫龅?/p>
圖 1 :洋蔥細(xì)胞的顯微鏡截圖,單元化要達(dá)到的目的就是讓每個(gè)單元像細(xì)胞一樣獨(dú)立工作
在傳統(tǒng)的服務(wù)化架構(gòu)下(如下圖),服務(wù)是分層的,每一層使用不同的分區(qū)算法,每一層都有不同數(shù)量的節(jié)點(diǎn),上層節(jié)點(diǎn)隨機(jī)選擇下層節(jié)點(diǎn)。當(dāng)然這個(gè)隨機(jī)是比較而言的。

單元化架構(gòu),為什么要用以及我們?nèi)绾巫龅?/p>
圖 2 :傳統(tǒng)的服務(wù)化架構(gòu),為伸縮性設(shè)計(jì),上層節(jié)點(diǎn)隨機(jī)選擇下層節(jié)點(diǎn)
與其不同的是,在單元化架構(gòu)下,服務(wù)雖然分層劃分,但每個(gè)單元自成一體。按照層次來(lái)講的話,所有層使用相同的分區(qū)算法,每一層都有相同數(shù)量的節(jié)點(diǎn),上層節(jié)點(diǎn)也會(huì)訪問(wèn)指定的下層節(jié)點(diǎn)。因?yàn)樗麄円呀?jīng)在一起。

單元化架構(gòu),為什么要用以及我們?nèi)绾巫龅?/p>
圖 3 :?jiǎn)卧軜?gòu),為性能和隔離性而設(shè)計(jì),上層節(jié)點(diǎn)訪問(wèn)指定下層節(jié)點(diǎn)
2. 為什么要用單元化
在性能追求和成本限制的情況下,我們需要找到一種合適的方法來(lái)滿足服務(wù)需求。在傳統(tǒng)的分布式服務(wù)設(shè)計(jì),我們考慮的更多是每個(gè)服務(wù)的可伸縮性,當(dāng)各個(gè)服務(wù)獨(dú)立設(shè)計(jì)時(shí)你就要在每一層進(jìn)行伸縮性的考慮。這是服務(wù)化設(shè)計(jì)(SOA)流行的原因,我們需要每個(gè)服務(wù)能夠單獨(dú)水平擴(kuò)展。
但是在摩爾定律下,隨著硬件的不斷升級(jí),計(jì)算機(jī)硬件能力已經(jīng)越來(lái)越強(qiáng),CPU 越來(lái)越快,內(nèi)存越來(lái)越大,網(wǎng)絡(luò)越來(lái)越寬。這讓我們看到了在單臺(tái)機(jī)器上垂直擴(kuò)展的機(jī)會(huì)。尤其是當(dāng)你遇到一個(gè)性能要求和容量增長(zhǎng)可以預(yù)期的業(yè)務(wù),單元化給我們提供另外的機(jī)會(huì),讓我們可以有效降低資源的使用,提供更高性能的服務(wù)。
總體而言,更高性能更低成本是我們的主要目標(biāo),而經(jīng)過(guò)單元化改造,我們得以用更少(約二分之一)的機(jī)器,獲得了比原來(lái)更高(接近百倍)的性能。性能的提升很大部分原因在于服務(wù)的本地化,而服務(wù)的集成部署又進(jìn)一步降低了資源的使用。
當(dāng)然除了性能收益,如果你做到了,你會(huì)發(fā)現(xiàn)還有很多收益,比如更好的隔離性,包括請(qǐng)求隔離和資源隔離,比如更友好的升級(jí),產(chǎn)品可以灰度發(fā)布等。單元化改造后對(duì)高峰的應(yīng)對(duì)以及擴(kuò)容方式等問(wèn)題,各位可以參考#微博春節(jié)技術(shù)保障系列#中的單元化架構(gòu)文章,也不在此一一贅述。
3. 我們?nèi)绾巫龅?/h1>
此次單元化改造基于微博現(xiàn)有的業(yè)務(wù),因此這里也先行介紹一下。粉絲服務(wù)平臺(tái)是微博的內(nèi)容推送系統(tǒng)(代號(hào) Castalia),可為 V 用戶提供向其粉絲推送高質(zhì)量?jī)?nèi)容的高速通道(單元化之后已到達(dá)百萬(wàn)條每秒)。整個(gè)服務(wù)涉及用戶篩選、發(fā)送計(jì)費(fèi)、屏蔽檢查、限流控制和消息群發(fā)等多個(gè)子服務(wù)。由于改造思想相通,這里以用戶篩選和消息群發(fā)兩個(gè)服務(wù)為例,下面兩圖分別為商業(yè)群發(fā)在服務(wù)化思想和單元化思想下不同的架構(gòu)。

圖 4: 服務(wù)化思想下的商業(yè)群發(fā)架構(gòu)設(shè)計(jì)(舊版)

圖 5 :商業(yè)群發(fā)在單元化思想下的架構(gòu)設(shè)計(jì)(新版)
對(duì)于篩選服務(wù),在服務(wù)化架構(gòu)里,需要去粉絲服務(wù)獲取粉絲關(guān)系,然后去特征服務(wù)進(jìn)行用戶特征篩選,最后將篩選結(jié)果傳輸?shù)饺喊l(fā)服務(wù)器上;而在單元化架構(gòu)里,粉絲關(guān)系直接就在本地文件中,用戶特征服務(wù)也在本地,最后的篩選結(jié)果再不需要傳輸。服務(wù)本地化(粉絲關(guān)系和用戶特征存儲(chǔ))減去了網(wǎng)絡(luò)開(kāi)銷,降低了服務(wù)延時(shí),還同時(shí)提高了訪問(wèn)速度和穩(wěn)定性,而篩選結(jié)果本地存儲(chǔ)又進(jìn)一步節(jié)省了帶寬并降低了延遲。以百萬(wàn)粉絲為例,每次網(wǎng)絡(luò)操作的減少節(jié)省帶寬 8M 左右,延時(shí)也從 400ms 降為 0。
群發(fā)服務(wù)同樣如此。由于在服務(wù)化架構(gòu)里,我們使用 MySQL 和 Memcache 的方案,由于關(guān)系數(shù)據(jù)庫(kù)的寫入性能問(wèn)題,中間還有隊(duì)列以及相應(yīng)的隊(duì)列處理機(jī),所有四個(gè)模塊都有單獨(dú)的機(jī)器提供服務(wù),而在單元化架構(gòu)里,四合一之后,只需要一套機(jī)器。當(dāng)然機(jī)器的配置可能會(huì)有所提升,但真正計(jì)算之后你就會(huì)發(fā)現(xiàn)其實(shí)影響微乎其微。原因除了前面介紹的硬件增長(zhǎng)空間外,上架機(jī)器的基本配置變高也是一個(gè)原因。而且,在單元化方案里,當(dāng)我們把緩存部署在本地之后,其性能還有了額外的 20% 提升。
一些業(yè)務(wù)特有問(wèn)題
不過(guò)群發(fā)這個(gè)場(chǎng)景,我們也遇到了一些特定的問(wèn)題,一是分區(qū)問(wèn)題,一是作業(yè)管理。這里也與各位分享下我們的解決方法。
1, 分區(qū)問(wèn)題
分區(qū)問(wèn)題其實(shí)是每個(gè)服務(wù)都會(huì)遇到的,但單元化后的挑戰(zhàn)在于讓所有服務(wù)都適配同一分區(qū)算法,在我們的場(chǎng)景下,我們按照接收者進(jìn)行了分區(qū),即從底層往上,每一層都來(lái)適配此分區(qū)算法。
這里有特例的是用戶特征和屏蔽服務(wù),由于總體容量都很小,我們就沒(méi)有對(duì)數(shù)據(jù)進(jìn)行分區(qū),所有單元內(nèi)都是同一套全量數(shù)據(jù),都是一個(gè)外部全量庫(kù)的從庫(kù)。不過(guò)由于本單元內(nèi)的上層服務(wù)的關(guān)系,只有屬于本分區(qū)的用戶數(shù)據(jù)被訪問(wèn)到。所以,適配同一分區(qū)算法在某種程度上講,可以兼容即可。
2, 作業(yè)管理
按照前面的分區(qū)方式,將群發(fā)服務(wù)的整體架構(gòu)變成了一個(gè)類似 Scatter-Gather+CQRS 的方案,因?yàn)?Gather 不是一個(gè)請(qǐng)求處理的必須要素。也就是說(shuō),一個(gè)群發(fā)請(qǐng)求會(huì)被擴(kuò)散到所有單元中,每個(gè)單元都要針對(duì)自己分區(qū)內(nèi)的用戶處理這個(gè)群發(fā)請(qǐng)求。
廣播方式的引入,使得我們首先需要在前端機(jī)進(jìn)行分單元作業(yè)的處理監(jiān)控,我們?cè)诖嗽黾恿顺志没?duì)列來(lái)解決。同時(shí),由于單元內(nèi)每個(gè)服務(wù)也都是單獨(dú)維護(hù)的,作業(yè)可能在任何時(shí)間中斷,因此每個(gè)作業(yè)在單元內(nèi)的狀態(tài)也都是有記錄的,以此來(lái)達(dá)到作業(yè)的可重入和冪等性,也就可以保證每個(gè)作業(yè)都可以在任何時(shí)間重做,但不會(huì)重復(fù)執(zhí)行。
除此之外,我們還對(duì)服務(wù)器進(jìn)行了更為精細(xì)的控制,使用 CPU 綁定提高多服務(wù)集成部署時(shí)的整體效率,使用多硬盤設(shè)計(jì)保證每個(gè)服務(wù)的 IO 性能,通過(guò)主從單元的讀寫分離來(lái)提高整體服務(wù)等等。
參考文章:https://www.infoq.cn/article/how-weibo-do-unit-architecture/
SOA架構(gòu)
SOA(Service-Oriented Architecture,面向服務(wù)的架構(gòu))是一個(gè)組件模型,它將應(yīng)用程序的不同功能單元(稱為服務(wù))通過(guò)這些服務(wù)之間定義良好的接口和契約聯(lián)系起來(lái)。接口是采用中立的方式進(jìn)行定義的,它應(yīng)該獨(dú)立于實(shí)現(xiàn)服務(wù)的硬件平臺(tái)、操作系統(tǒng)和編程語(yǔ)言。這使得構(gòu)建在各種各樣的系統(tǒng)中的服務(wù)可以以一種統(tǒng)一和通用的方式進(jìn)行交互。面向服務(wù)架構(gòu),它可以根據(jù)需求通過(guò)網(wǎng)絡(luò)對(duì)松散耦合的粗粒度應(yīng)用組件進(jìn)行分布式部署、組合和使用。服務(wù)層是 SOA 的基礎(chǔ),可以直接被應(yīng)用調(diào)用,從而有效控制系統(tǒng)中與軟件代理交互的人為依賴性。
SOA的實(shí)施具有幾個(gè)鮮明的基本特征。實(shí)施 SOA 的關(guān)鍵目標(biāo)是實(shí)現(xiàn)企業(yè) IT 資產(chǎn)的最大化作用。要實(shí)現(xiàn)這一目標(biāo),就要在實(shí)施 SOA 的過(guò)程中牢記以下特征:
- 可從企業(yè)外部訪問(wèn);
- 隨時(shí)可用;
- 粗粒度的服務(wù)接口分級(jí);
- 松散耦合;
- 可重用的服務(wù);
- 服務(wù)接口設(shè)計(jì)管理;
- 標(biāo)準(zhǔn)化的服務(wù)接口;
- 支持各種消息模式;
- 精確定義的服務(wù)契約。
為了實(shí)現(xiàn) SOA,企業(yè)需要一個(gè)服務(wù)架構(gòu),下圖顯示了一個(gè)例子:

在上圖中, 服務(wù)消費(fèi)者(service consumer)可以通過(guò)發(fā)送消息來(lái)調(diào)用服務(wù)。這些消息由一個(gè)服務(wù)總線(service bus)轉(zhuǎn)換后發(fā)送給適當(dāng)?shù)姆?wù)實(shí)現(xiàn)。這種服務(wù)架構(gòu)可以提供一個(gè)業(yè)務(wù)規(guī)則引(business rules engine),該引擎容許業(yè)務(wù)規(guī)則被合并在一個(gè)服務(wù)里或多個(gè)服務(wù)里。這種架構(gòu)也提供了一個(gè)服務(wù)管理基礎(chǔ)(service management infrastructure),用來(lái)管理服務(wù),類似審核,列表(billing),日志等功能。
此外,該架構(gòu)給企業(yè)提供了靈活的業(yè)務(wù)流程,更好地處理控制請(qǐng)求(regulatory requirement),例如Sarbanes Oxley(SOX),并且可以在不影響其他服務(wù)的情況下更改某項(xiàng)服務(wù)。
微服務(wù)架構(gòu)
先來(lái)看看傳統(tǒng)的 web 開(kāi)發(fā)方式,通過(guò)對(duì)比比較容易理解什么是 Microservice Architecture。和 Microservice 相對(duì)應(yīng)的,這種方式一般被稱為 Monolithic(單體式開(kāi)發(fā))。
所有的功能打包在一個(gè) WAR包里,基本沒(méi)有外部依賴(除了容器),部署在一個(gè)JEE容器(Tomcat,JBoss,WebLogic)里,包含了 DO/DAO,Service,UI 等所有邏輯。
1、優(yōu)點(diǎn):
- 開(kāi)發(fā)簡(jiǎn)單,集中式管理;
- 基本不會(huì)重復(fù)開(kāi)發(fā);
- 功能都在本地,沒(méi)有分布式的管理和調(diào)用消耗。
2、缺點(diǎn):
- 效率低:開(kāi)發(fā)都在同一個(gè)項(xiàng)目改代碼,相互等待,沖突不斷;
- 維護(hù)難:代碼功功能耦合在一起,新人不知道何從下手;
- 不靈活:構(gòu)建時(shí)間長(zhǎng),任何小修改都要重構(gòu)整個(gè)項(xiàng)目,耗時(shí);
- 穩(wěn)定性差:一個(gè)微小的問(wèn)題,都可能導(dǎo)致整個(gè)應(yīng)用掛掉;
- 擴(kuò)展性不夠:無(wú)法滿足高并發(fā)下的業(yè)務(wù)需求。
3、常見(jiàn)的系統(tǒng)架構(gòu)遵循的三個(gè)標(biāo)準(zhǔn)和業(yè)務(wù)驅(qū)動(dòng)力:
- 提高敏捷性:及時(shí)響應(yīng)業(yè)務(wù)需求,促進(jìn)企業(yè)發(fā)展;
- 提升用戶體驗(yàn):提升用戶體驗(yàn),減少用戶流失;
- 降低成本:降低增加產(chǎn)品、客戶或業(yè)務(wù)方案的成本。
4、基于微服務(wù)架構(gòu)的設(shè)計(jì):
目的:有效的拆分應(yīng)用,實(shí)現(xiàn)敏捷開(kāi)發(fā)和部署。

關(guān)于微服務(wù)的一個(gè)形象表達(dá):

- X軸:運(yùn)行多個(gè)負(fù)載均衡器之后的運(yùn)行實(shí)例;
- Y軸:將應(yīng)用進(jìn)一步分解為微服務(wù)(分庫(kù));
- Z軸:大數(shù)據(jù)量時(shí),將服務(wù)分區(qū)(分表)。
5、SOA和微服務(wù)的區(qū)別:
- SOA喜歡重用,微服務(wù)喜歡重寫;
- SOA喜歡水平服務(wù),微服務(wù)喜歡垂直服務(wù);
- SOA喜歡自上而下,微服務(wù)喜歡自下而上。
Serverless架構(gòu)
1、思想:無(wú)服務(wù)器是一種架構(gòu)理念,其核心思想是將提供服務(wù)資源的基礎(chǔ)設(shè)施抽象成各種服務(wù),以 API 接口的方式供給用戶按需調(diào)用,真正做到按需伸縮、按使用收費(fèi)。
2、優(yōu)勢(shì):消除了對(duì)傳統(tǒng)的海量持續(xù)在線服務(wù)器組件的需求,降低了開(kāi)發(fā)和運(yùn)維的復(fù)雜性,降低運(yùn)營(yíng)成本并縮短了業(yè)務(wù)系統(tǒng)的交付周期,使得用戶能夠?qū)W⒃趦r(jià)值密度更高的業(yè)務(wù)邏輯的開(kāi)發(fā)上。
3、內(nèi)容:目前業(yè)界較為公認(rèn)的無(wú)服務(wù)器架構(gòu)主要包括兩個(gè)方面,即提供計(jì)算資源的函數(shù)服務(wù)平臺(tái) FaaS,以及提供托管云服務(wù)的后端服務(wù) BaaS。
函數(shù)即服務(wù)(Function as a Service):是一項(xiàng)基于事件驅(qū)動(dòng)的函數(shù)托管計(jì)算服務(wù)。通過(guò)函數(shù)服務(wù),開(kāi)發(fā)者只需要編寫業(yè)務(wù)函數(shù)代碼并設(shè)置運(yùn)行的條件,無(wú)需配置和管理服務(wù)器等基礎(chǔ)設(shè)施,函數(shù)代碼運(yùn)行在無(wú)狀態(tài)的容器中,由事件觸發(fā)且短暫易失,并完全由第三方管理,基礎(chǔ)設(shè)施對(duì)應(yīng)用開(kāi)發(fā)者完全透明。函數(shù)以彈性、高可靠的方式運(yùn)行,并且按實(shí)際執(zhí)行資源計(jì)費(fèi),不執(zhí)行不產(chǎn)生費(fèi)用。
后端即服務(wù)(Backend as a Service):BaaS 覆蓋了應(yīng)用可能依賴的所有第三方服務(wù),如云數(shù)據(jù)庫(kù)、身份驗(yàn)證、對(duì)象存儲(chǔ)等服務(wù),開(kāi)發(fā)人員通過(guò) API 和由 BaaS 服務(wù)商提供的 SDK,能夠集成所需的所有后端功能,而無(wú)需構(gòu)建后端應(yīng)用,更不必管理虛擬機(jī)或容器等基礎(chǔ)設(shè)施,就能保證應(yīng)用的正常運(yùn)行。

三個(gè)less感覺(jué)很好:
- Codeless 對(duì)應(yīng)的是服務(wù)開(kāi)發(fā),實(shí)現(xiàn)了源代碼托管,你只需要關(guān)注你的代碼實(shí)現(xiàn),而不需要關(guān)心你的代碼在哪,因?yàn)樵谡麄€(gè)開(kāi)發(fā)過(guò)程中你都不會(huì)感受到代碼庫(kù)和代碼分支的存在。
- Applicationless 對(duì)應(yīng)的是服務(wù)發(fā)布,在服務(wù)化框架下,你的服務(wù)發(fā)布不再需要申請(qǐng)應(yīng)用,也不需要關(guān)注你的應(yīng)用在哪。
- Serverless 對(duì)應(yīng)的則是服務(wù)運(yùn)維,有了 Serverless 化能力,你不再需要關(guān)注你的機(jī)器資源,Servlerless 會(huì)幫你搞定機(jī)器資源的彈性擴(kuò)縮容。
架構(gòu)師在完成上述架構(gòu)設(shè)計(jì)后,最終是需要協(xié)同利益相關(guān)方一起按項(xiàng)目化運(yùn)作落地拿結(jié)果,那么應(yīng)該如何保證利益相關(guān)方在項(xiàng)目落地的滿意度,如何保證按照架構(gòu)很好的拿到項(xiàng)目成功的結(jié)果呢?架構(gòu)管理能力是架構(gòu)師非常重要的能力。
架構(gòu)師管理架構(gòu)雙贏模型

架構(gòu)結(jié)果管理

優(yōu)秀架構(gòu)師必須掌握的幾種架構(gòu)思維
架構(gòu)的本質(zhì)是管理復(fù)雜性,抽象、分層、分治和演化思維是我們工程師/架構(gòu)師應(yīng)對(duì)和管理復(fù)雜性的四種最基本武器。
最近團(tuán)隊(duì)來(lái)了一些新人,有些有一定工作經(jīng)驗(yàn),是以高級(jí)工程師/架構(gòu)師身份進(jìn)來(lái)的,但我發(fā)現(xiàn)他們大部分人思維偏應(yīng)用和細(xì)節(jié),抽象能力弱。所以作為團(tuán)隊(duì)技術(shù)培訓(xùn)的一部分,我整理了這篇文章,希望對(duì)他們樹(shù)立正確的架構(gòu)設(shè)計(jì)思維有幫助。我認(rèn)為,對(duì)思維習(xí)慣和思考能力的培養(yǎng),其重要性遠(yuǎn)遠(yuǎn)大于對(duì)實(shí)際技術(shù)工具的掌握。
由于文章內(nèi)容較長(zhǎng),所以我把它分成兩篇小文章,在第一篇《優(yōu)秀架構(gòu)師必須掌握的架構(gòu)思維》中,我會(huì)先介紹抽象、分層、分治和演化這四種應(yīng)對(duì)復(fù)雜性的基本思維。在第二篇《四個(gè)架構(gòu)設(shè)計(jì)案例及其思維方式》中,我會(huì)通過(guò)四個(gè)案例,講解如何綜合運(yùn)用這些思維,分別對(duì)小型系統(tǒng),中型系統(tǒng),基礎(chǔ)架構(gòu),甚至是組織技術(shù)體系進(jìn)行架構(gòu)和設(shè)計(jì)。
一、抽象思維
如果要問(wèn)軟件研發(fā)/系統(tǒng)架構(gòu)中最重要的能力是什么,我會(huì)毫不猶豫回答是抽象能力。抽象(abstraction)這個(gè)詞大家經(jīng)常聽(tīng)到,但是真正理解和能講清楚什么是抽象的人少之又少。抽象其實(shí)是這樣定義的:
對(duì)某種事物進(jìn)行簡(jiǎn)化表示或描述的過(guò)程,抽象讓我們關(guān)注要素,隱藏額外細(xì)節(jié)。
舉一個(gè)例子,見(jiàn)下圖:

你看到什么?你看到的是一扇門,對(duì)不對(duì)?你看到的不是木頭,也不是碳原子,這個(gè)門就是抽象,而木頭或者碳原子是細(xì)節(jié)。另外你可以看到門上有個(gè)門把手,你看到的不是鐵,也不是鐵原子,門把手就是抽象,鐵和鐵原子是細(xì)節(jié)。
在系統(tǒng)架構(gòu)和設(shè)計(jì)中,抽象幫助我們從大處著眼(get our mind about big picture),隱藏細(xì)節(jié)(temporarily hide details)。抽象能力的強(qiáng)弱,直接決定我們所能解決問(wèn)題的復(fù)雜性和規(guī)模大小。
下圖是我們小時(shí)候玩的積木,我發(fā)現(xiàn)小時(shí)候喜歡玩搭積木的,并且搭得快和好的小朋友,一般抽象能力都比較強(qiáng)。

上圖右邊的積木城堡就是抽象,這個(gè)城堡如果你細(xì)看的話,它其實(shí)還是由若干個(gè)子模塊組成,這些模塊是子抽象單元,左邊的各種形狀的積木是細(xì)節(jié)。搭積木的時(shí)候,小朋友腦袋里頭先有一個(gè)城堡的大圖(抽象),然后他/她大腦里頭會(huì)有一個(gè)初步的子模塊分解(潛意識(shí)中完成),然用利用積木搭建每一個(gè)子模塊,最終拼裝出最后的城堡。這里頭有一個(gè)自頂向下的分治設(shè)計(jì),然后自底向上的組合過(guò)程,這個(gè)分治思維非常重要,我們后面會(huì)講。
我認(rèn)為軟件系統(tǒng)架構(gòu)設(shè)計(jì)和小朋友搭積木無(wú)本質(zhì)差異,只是解決的問(wèn)題域和規(guī)模不同罷了。架構(gòu)師先要在大腦中形成抽象概念,然后是子模塊分解,然后是依次實(shí)現(xiàn)子模塊,最后將子模塊拼裝組合起來(lái),形成最后系統(tǒng)。所以我常說(shuō)編程和架構(gòu)設(shè)計(jì)就是搭積木,優(yōu)秀的架構(gòu)師受職業(yè)習(xí)慣影響,眼睛里看到的世界都是模塊化拼裝組合式的。
抽象能力不僅對(duì)軟件系統(tǒng)架構(gòu)設(shè)計(jì)重要,對(duì)建筑、商業(yè)、管理等人類其它領(lǐng)域活動(dòng)同樣非常重要。其實(shí)可以這樣認(rèn)為,我們生存的世界都是在抽象的基礎(chǔ)上構(gòu)建起來(lái)的,離開(kāi)抽象人類將寸步難行。
這里順便提一下抽象層次跳躍問(wèn)題,這個(gè)在開(kāi)發(fā)中是蠻普遍的。有經(jīng)驗(yàn)的程序員寫代碼會(huì)保持抽象層次的一致性,代碼讀起來(lái)像講故事,比較清晰易于理解;而沒(méi)有經(jīng)驗(yàn)的程序員會(huì)有明顯的抽象層次跳躍問(wèn)題,代碼讀起來(lái)就比較累,這個(gè)是抽象能力不足造成。舉個(gè)例子:

一個(gè)電商網(wǎng)站在處理訂單時(shí),一般會(huì)走這樣一個(gè)流程:
- 更新庫(kù)存(InventoryUpdate)
- 打折計(jì)算(Discounting)
- 支付卡校驗(yàn)(PaycardVerification)
- 支付(Pay)
- 送貨(Shipping)
上述流程中的抽象是在同一個(gè)層次上的,比較清晰易于理解,但是沒(méi)有經(jīng)驗(yàn)的程序員在實(shí)現(xiàn)這個(gè)流程的時(shí)候,代碼層次會(huì)跳,比方說(shuō)主流程到支付卡校驗(yàn)一塊,他的代碼會(huì)突然跳出一行某銀行API遠(yuǎn)程調(diào)用,這個(gè)就是抽象跳躍,銀行API調(diào)用是細(xì)節(jié),應(yīng)該封裝在PaycardVerification這個(gè)抽象里頭。
二、分層思維
除了抽象,分層也是我們應(yīng)對(duì)和管理復(fù)雜性的基本思維武器,如下圖,為了構(gòu)建一套復(fù)雜系統(tǒng),我們把整個(gè)系統(tǒng)劃分成若干個(gè)層次,每一層專注解決某個(gè)領(lǐng)域的問(wèn)題,并向上提供服務(wù)。有些層次是縱向的,它貫穿所有其它層次,稱為共享層。分層也可以認(rèn)為是抽象的一種方式,將系統(tǒng)抽象分解成若干層次化的模塊。

分層架構(gòu)的案例很多,一個(gè)中小型的Spring Web應(yīng)用程序,我們一般會(huì)設(shè)計(jì)成三層架構(gòu):

操作系統(tǒng)是經(jīng)典的分層架構(gòu),如下圖:

TCP/IP協(xié)議棧也是經(jīng)典的分層架構(gòu),如下圖:

如果你關(guān)注人類文明演化史,你會(huì)發(fā)現(xiàn)今天的人類世界也是以分層方式一層層搭建和演化出來(lái)的。今天的互聯(lián)網(wǎng)系統(tǒng)可以認(rèn)為是現(xiàn)代文明的一個(gè)層次,其上是基于互聯(lián)網(wǎng)的現(xiàn)代商業(yè),其下是現(xiàn)代電子工業(yè)基礎(chǔ)設(shè)施,諸如此類。
三、分治思維
分而治之(divide and combine或者split and merge)也是應(yīng)對(duì)和管理復(fù)雜性的一般性方法,下圖展示一個(gè)分治的思維流程:

對(duì)于一個(gè)無(wú)法一次解決的大問(wèn)題,我們會(huì)先把大問(wèn)題分解成若干個(gè)子問(wèn)題,如果子問(wèn)題還無(wú)法直接解決,則繼續(xù)分解成子子問(wèn)題,直到可以直接解決的程度,這個(gè)是分解(divide)的過(guò)程;然后將子子問(wèn)題的解組合拼裝成子問(wèn)題的解,再將子問(wèn)題的解組合拼裝成原問(wèn)題的解,這個(gè)是組合(combine)的過(guò)程。
面試時(shí)為了考察候選人的分治思維,我經(jīng)常會(huì)面一個(gè)分治題:給你一臺(tái)8G內(nèi)存/500G磁盤空間的普通電腦,如何對(duì)一個(gè)100G的大文件進(jìn)行排序?假定文件中都是字符串記錄,一行約100個(gè)字符。
這是一個(gè)典型的分治問(wèn)題,100G的大文件肯定無(wú)法一次加載到內(nèi)存直接排序,所以需要先切分成若干小問(wèn)題來(lái)解決。那么8G內(nèi)存的計(jì)算機(jī)一次大概能排多大的數(shù)據(jù)量,可以在有限的時(shí)間內(nèi)排完呢?也就是100G的大文件要怎么切法,切成多少份比較合適?這個(gè)是考察候選人的時(shí)間空間復(fù)雜度估算能力,需要一定的計(jì)算機(jī)組織和算法功底,也需要一定實(shí)戰(zhàn)經(jīng)驗(yàn)和sense。實(shí)際上8G內(nèi)存的話,操作系統(tǒng)要用掉一部分,如果用JAVA開(kāi)發(fā)排序程序,大致JVM可用2~4G內(nèi)存,基于一般的經(jīng)驗(yàn)值,一次排1G左右的數(shù)據(jù)應(yīng)該沒(méi)有問(wèn)題(我實(shí)際在計(jì)算機(jī)上干過(guò)1G數(shù)據(jù)的排序,是OK的)。所以100G的文件需要先切分成100份,每份1G,這樣每個(gè)子文件可以直接加載到內(nèi)存進(jìn)行排序。對(duì)于1G數(shù)據(jù)量的字符串排序,采用Java里頭提供的快速排序算法是比較合適的。
好,經(jīng)過(guò)有限時(shí)間的排序(取決于計(jì)算機(jī)性能,快的一天內(nèi)能排完),假定100個(gè)1G的文件都已經(jīng)排好了,相當(dāng)于現(xiàn)在硬盤上有100個(gè)已經(jīng)排好序的文件,但是我們最終需要的是一個(gè)排好序的文件,下面該怎么做?這個(gè)時(shí)候我們需要把已經(jīng)解決的子問(wèn)題組合起來(lái),合并成我們需要的最終結(jié)果文件。這個(gè)時(shí)候該采用什么算法呢?這里考察候選人對(duì)外排序和歸并排序算法的掌握程度,我們可以將100個(gè)排好序的文件進(jìn)行兩兩歸并排序,這樣不斷重復(fù),我們就會(huì)得到50個(gè)排好序的文件,每個(gè)大小是2G。然后再兩兩歸并,不斷重復(fù),直到最后兩個(gè)文件歸并成目標(biāo)文件,這個(gè)文件就是100G并且是排好序的。因?yàn)槭峭馀判?歸并排序,每次只需要讀取當(dāng)前索引指向的文件記錄到內(nèi)存,進(jìn)行比較,小的那個(gè)輸出到目標(biāo)文件,內(nèi)存占用極少。另外,上面的算法是兩路歸并,也可以采用多路歸并,甚至是采用堆排序進(jìn)行優(yōu)化,但是總體分治思路沒(méi)有變化。
總體上這是一個(gè)非常好的面試題,除了考察候選人的分治思維之外,還考察對(duì)各種排序算法(快排,外排序,歸并排序,堆排序)的理解,計(jì)算的時(shí)間空間復(fù)雜度估算,計(jì)算機(jī)的內(nèi)外存特性和組織,文件操作等等。實(shí)際上能完全回答清楚這個(gè)問(wèn)題的候選人極少,如果有幸被我面到一個(gè),我會(huì)如獲至寶,因?yàn)檫@個(gè)人有成長(zhǎng)為優(yōu)秀架構(gòu)師的潛質(zhì)。
另外,遞歸也是一種特殊的分治技術(shù),掌握遞歸技術(shù)的開(kāi)發(fā)人員,相當(dāng)于掌握了一種強(qiáng)大的編程武器,可以解決一些一般開(kāi)發(fā)人員無(wú)法解決的問(wèn)題。比方說(shuō)最近我的團(tuán)隊(duì)在研發(fā)一款新的服務(wù)框架,其中包括契約解析器(parser),代碼生產(chǎn)器(code generator),序列化器(serializer)等組件,里頭大量需要用到遞歸的思維和技術(shù),沒(méi)有這個(gè)思維的開(kāi)發(fā)人員就干不了這個(gè)事情。所以我在面試候選人的時(shí)候,一般都會(huì)出遞歸相關(guān)的編程題,考察候選人的遞歸思維。
大自然中遞歸結(jié)構(gòu)比比皆是,如下圖,大家有興趣不妨思考,大自然通過(guò)遞歸給我們?nèi)祟惡畏N啟示?


四、演化思維
社區(qū)里頭經(jīng)常有人在討論:架構(gòu)是設(shè)計(jì)出來(lái)的?還是演化出來(lái)的?我個(gè)人基于十多年的經(jīng)驗(yàn)認(rèn)為,架構(gòu)既是設(shè)計(jì)出來(lái)的,同時(shí)也是演化出來(lái)的,對(duì)于互聯(lián)網(wǎng)系統(tǒng),基本上可以說(shuō)是三分設(shè)計(jì),七分演化,而且是在設(shè)計(jì)中演化,在演化中設(shè)計(jì),一個(gè)不斷迭代的過(guò)程。
在互聯(lián)網(wǎng)軟件系統(tǒng)的整個(gè)生命周期過(guò)程中,前期的設(shè)計(jì)和開(kāi)發(fā)大致只占三分,在后面的七分時(shí)間里,架構(gòu)師需要根據(jù)用戶的反饋對(duì)架構(gòu)進(jìn)行不斷的調(diào)整。我認(rèn)為架構(gòu)師除了要利用自身的架構(gòu)設(shè)計(jì)能力,同時(shí)也要學(xué)會(huì)借助用戶反饋和進(jìn)化的力量,推動(dòng)架構(gòu)的持續(xù)演進(jìn),這個(gè)就是演化式架構(gòu)思維。
當(dāng)然一開(kāi)始的架構(gòu)設(shè)計(jì)非常重要,架構(gòu)定系統(tǒng)基本就成型了,不容馬虎。同時(shí),優(yōu)秀的架構(gòu)師深知,能夠不斷應(yīng)對(duì)環(huán)境變化的系統(tǒng),才是有生命力的系統(tǒng),架構(gòu)的好壞,很大部分取決于它應(yīng)對(duì)變化的靈活性。所以具有演化式思維的架構(gòu)師,能夠在一開(kāi)始設(shè)計(jì)時(shí)就考慮到后續(xù)架構(gòu)的演化特性,并且將靈活應(yīng)對(duì)變化的能力作為架構(gòu)設(shè)計(jì)的主要考量。
當(dāng)前,社區(qū)正在興起一種新的架構(gòu)方法學(xué)~演化式架構(gòu),微服務(wù)架構(gòu)就是一種典型的演化式架構(gòu),它能夠快速響應(yīng)市場(chǎng)用戶需求的變化,而單塊架構(gòu)就缺乏這種靈活性。馬丁·福樂(lè)曾經(jīng)在其博客上給出過(guò)一張微服務(wù)架構(gòu)的演化路線圖[附錄8.2],可以用來(lái)解釋設(shè)計(jì)式思維和演化式思維的差異,如下圖所示:

上面的路線是一開(kāi)始就直奔微服務(wù)架構(gòu),其實(shí)背后體現(xiàn)的是設(shè)計(jì)式架構(gòu)的思維,認(rèn)為架構(gòu)師可以完全設(shè)計(jì)整個(gè)系統(tǒng)和它的演化方向。馬丁認(rèn)為這種做法風(fēng)險(xiǎn)非常高,一個(gè)是成本高昂,另外一個(gè)是剛開(kāi)始架構(gòu)師對(duì)業(yè)務(wù)域理解不深,無(wú)法清晰劃分領(lǐng)域邊界,開(kāi)發(fā)出來(lái)的系統(tǒng)很可能無(wú)法滿足用戶需求。
下面的路線是從單塊架構(gòu)開(kāi)始,隨著架構(gòu)師對(duì)業(yè)務(wù)域理解的不斷深入,也隨著業(yè)務(wù)和團(tuán)隊(duì)規(guī)模的不斷擴(kuò)大,漸進(jìn)式地把單塊架構(gòu)拆分成微服務(wù)架構(gòu)的思路,這就是演化式架構(gòu)的思維。如果你觀察現(xiàn)實(shí)世界中一些互聯(lián)網(wǎng)公司(例如eBay,阿里,Netflix等等)的系統(tǒng)架構(gòu),大部分走得都是演化式架構(gòu)的路線。
下圖是建筑的演化史,在每個(gè)階段,你可以看到設(shè)計(jì)的影子,但如果時(shí)間線拉得足夠長(zhǎng),演化的特性就出來(lái)了。

五、如何培養(yǎng)架構(gòu)設(shè)計(jì)思維
良好的架構(gòu)設(shè)計(jì)思維的培養(yǎng),離不開(kāi)工作中大量高質(zhì)量項(xiàng)目的實(shí)戰(zhàn)鍛煉,然后是平時(shí)的學(xué)習(xí)、思考和提煉總結(jié)。
另外,基本的架構(gòu)設(shè)計(jì)思維,其實(shí)在我們大學(xué)計(jì)算機(jī)課程(比如數(shù)據(jù)結(jié)構(gòu)和算法)中可以找到影子,只不過(guò)當(dāng)時(shí)以學(xué)習(xí)為主,問(wèn)題域比較小和理想化。所以大學(xué)教育其實(shí)非常重要,基本的架構(gòu)設(shè)計(jì)思維在那個(gè)時(shí)候就已經(jīng)埋下種子,后面工程實(shí)踐中進(jìn)一步消化和應(yīng)用,隨著經(jīng)驗(yàn)的積累,我們能夠解決的問(wèn)題域復(fù)雜性和規(guī)模逐漸變大,但基本的武器還是抽象、分層和分治等思維。
我認(rèn)為一個(gè)架構(gòu)師的成長(zhǎng)高度和他大學(xué)期間的思維習(xí)慣的養(yǎng)成關(guān)系密切。我所知道世界一流的互聯(lián)網(wǎng)公司,例如谷歌等,招聘工程師新人時(shí),對(duì)數(shù)據(jù)結(jié)構(gòu)和算法的要求可以用苛刻來(lái)形容,這個(gè)可以理解,谷歌級(jí)別公司要解決的問(wèn)題都是超級(jí)復(fù)雜的,基本思維功底薄弱根本無(wú)法應(yīng)對(duì)。
對(duì)于工作經(jīng)驗(yàn)<5年的工程師新手,如果你大學(xué)時(shí)代是屬于荒廢型的,建議工作之余把相關(guān)課程再好好自學(xué)一把。個(gè)人推薦參考美國(guó)Berkeley大學(xué)的數(shù)據(jù)結(jié)構(gòu)課程CS61B[附錄8.1]進(jìn)行學(xué)習(xí),對(duì)建立抽象編程思維非常有幫助,我本人在研究生階段自學(xué)過(guò)這門課程,現(xiàn)在回想起來(lái)確實(shí)受益匪淺,注意該課程中的所有Lab/Homework/Project都要實(shí)際動(dòng)手做一遍,才有好的效果。

對(duì)于演化設(shè)計(jì)思維,當(dāng)前的大學(xué)教育其實(shí)培養(yǎng)很少,相反,當(dāng)前大學(xué)教育大都采用脫離現(xiàn)實(shí)場(chǎng)景的簡(jiǎn)化理想模型,有些還是固定答案的應(yīng)試教學(xué),這種方式會(huì)造成學(xué)生思維確定化,不利于培養(yǎng)演化式設(shè)計(jì)思維。我個(gè)人的體會(huì),演化式設(shè)計(jì)思維更多在實(shí)際工作中通過(guò)實(shí)戰(zhàn)鍛煉和培養(yǎng)。
結(jié)論
架構(gòu)的本質(zhì)是管理復(fù)雜性,抽象、分層、分治和演化思維是架構(gòu)師征服復(fù)雜性的四種根本性武器。
掌握了抽象、分層、分治和演化這四種基本的武器,你可以設(shè)計(jì)小到一個(gè)類,一個(gè)模塊,一個(gè)子系統(tǒng),或者一個(gè)中型的系統(tǒng),也可以大到一個(gè)公司的基礎(chǔ)平臺(tái)架構(gòu),微服務(wù)架構(gòu),技術(shù)體系架構(gòu),甚至是組織架構(gòu),業(yè)務(wù)架構(gòu)等等。
架構(gòu)設(shè)計(jì)不是靜態(tài)的,而是動(dòng)態(tài)演化的。只有能夠不斷應(yīng)對(duì)環(huán)境變化的系統(tǒng),才是有生命力的系統(tǒng)。所以即使你掌握了抽象、分層和分治這三種基本思維,仍然需要演化式思維,在設(shè)計(jì)的同時(shí),借助反饋和進(jìn)化的力量推動(dòng)架構(gòu)的持續(xù)演進(jìn)。
架構(gòu)師在關(guān)注技術(shù),開(kāi)發(fā)應(yīng)用的同時(shí),需要定期梳理自己的架構(gòu)設(shè)計(jì)思維,積累時(shí)間長(zhǎng)了,你看待世界事物的方式會(huì)發(fā)生根本性變化,你會(huì)發(fā)現(xiàn)我們生活其中的世界,其實(shí)也是在抽象、分層、分治和演化的基礎(chǔ)上構(gòu)建起來(lái)的。另外架構(gòu)設(shè)計(jì)思維的形成,會(huì)對(duì)你的系統(tǒng)架構(gòu)設(shè)計(jì)能力產(chǎn)生重大影響。可以說(shuō)對(duì)抽象、分層、分治和演化掌握的深度和靈活應(yīng)用的水平,直接決定架構(gòu)師所能解決問(wèn)題域的復(fù)雜性和規(guī)模大小,是區(qū)分普通應(yīng)用型架構(gòu)師和平臺(tái)型/系統(tǒng)型架構(gòu)師的一個(gè)分水嶺。
原文鏈接:https://blog.csdn.net/universsky2015/article/details/102397412