網(wǎng)站性能檢測(cè)評(píng)分
注:本網(wǎng)站頁(yè)面html檢測(cè)工具掃描網(wǎng)站中存在的基本問(wèn)題,僅供參考。
信息架構(gòu)設(shè)計(jì)
架構(gòu)師必須知道的架構(gòu)設(shè)計(jì)原則 推廣視頻課程
不管你是新手程序員、職場(chǎng)老司機(jī),還是資深架構(gòu)師,這篇文章對(duì)你來(lái)說(shuō)應(yīng)該都有裨益。雖然仍是假期,但也建議你多花點(diǎn)時(shí)間讀一讀這些真言。
寫(xiě)在前面
如果一個(gè)技術(shù)已經(jīng)存在 2 年,比如現(xiàn)在很火的前端技術(shù) react 和 vue 等,那么我能預(yù)估這個(gè)技術(shù)大致還有 2 年的生命期,再久就不確定了;如果一個(gè)架構(gòu)或設(shè)計(jì)原則已經(jīng)存在 15 年,例如單一職責(zé)和依賴(lài)倒置原則,我可以預(yù)期它還有 15 年甚至更久的生命期。原則是比具體技術(shù)更抽象,更接近事物本質(zhì),也更經(jīng)得起時(shí)間考驗(yàn)的東西。這些原則沉淀在架構(gòu)師的腦海中,最終內(nèi)化成他的 mindset,以潛意識(shí)方式影響和指導(dǎo)他的架構(gòu)和設(shè)計(jì)工作。
一晃我在軟件研發(fā)行業(yè)工作十多個(gè)年頭了,前面大部分時(shí)間做架構(gòu)設(shè)計(jì)和開(kāi)發(fā),現(xiàn)在轉(zhuǎn)型做研發(fā)管理。隨著時(shí)間的推移,很多技戰(zhàn)術(shù)細(xì)節(jié)性的東西 (工具,框架,編程語(yǔ)言) 在我腦海中漸漸模糊,但是一些平時(shí)學(xué)習(xí)積累起來(lái),并且在實(shí)踐中加深體會(huì)的軟件架構(gòu)設(shè)計(jì)和組織原則,這些原則性的東西卻絲毫沒(méi)有被時(shí)間沖淡,反而愈加清新?,F(xiàn)在即使我不在一線開(kāi)發(fā),但這些沉淀下來(lái)的原則仍然潛移默化地影響我的日常管理和部分架構(gòu)設(shè)計(jì)指導(dǎo)工作。我想有必要總結(jié)一下那些業(yè)界知名,給我留下深刻印象的軟件架構(gòu)設(shè)計(jì)和組織原則,和大家一起分享。
軟件設(shè)計(jì)原則GRASP 通用職責(zé)分配軟件模式
來(lái)自 Craig Larman 的軟件設(shè)計(jì)書(shū)《UML 和模式應(yīng)用》[附錄 1],Larman 在書(shū)中提出軟件設(shè)計(jì)的關(guān)鍵任務(wù)是職責(zé)分配,并提煉總結(jié)出 9 種 (5 種核心 +4 種擴(kuò)展) 軟件職責(zé)分配模式,這些模式是比 GoF 設(shè)計(jì)模式更抽象的元模式。
1. 信息專(zhuān)家 (Information Expert)
為對(duì)象分配職責(zé)的通用原則 – 把職責(zé)分配給擁有足夠信息可以履行職責(zé)的專(zhuān)家
2. 創(chuàng)建者 (Creator)
將創(chuàng)建 A 的職責(zé)賦給 B,如果至少下面一種情況為真:
B“包含”或者聚合 AB 記錄 A 的實(shí)例B 密切地使用 AB 擁有 A 的初始化數(shù)據(jù)
3. 低耦合 (Low Coupling)
賦予職責(zé)使得對(duì)象間的耦合度盡可能低,最小化對(duì)象間的依賴(lài)和變更影響,最大化重用。
4. 高內(nèi)聚 (High Cohesion)
賦予職責(zé)使得每個(gè)對(duì)象的職責(zé)盡可能保持聚焦和單一,易于管理和理解。
5. 控制器 (Controller)
把職責(zé)賦予系統(tǒng)、設(shè)備或者子系統(tǒng)的表示類(lèi) (門(mén)面控制器),或者某個(gè)用例的表示類(lèi) (用例控制器),讓控制器接收事件并協(xié)調(diào)整個(gè)系統(tǒng)的運(yùn)作。
6. 多態(tài) (Polymorphism)
將職責(zé)分配給多個(gè)具有同名方法的多態(tài)子類(lèi),運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)切換子類(lèi),讓系統(tǒng)行為變得可插拔。
7. 純虛構(gòu) (Pure Fabrication)
針對(duì)真實(shí)問(wèn)題域中不存在,但是設(shè)計(jì)建模中有用的概念,設(shè)計(jì)虛構(gòu)類(lèi)并賦予職責(zé)。
8. 間接 (Indirection)
在兩個(gè)或者多個(gè)對(duì)象間有交互的情況下,為避免直接耦合,提高重用性,創(chuàng)建中間類(lèi)并賦予職責(zé),對(duì)象的交互交由中間類(lèi)協(xié)調(diào)。
9. 受保護(hù)的變化 (Protected Variation)
簡(jiǎn)單講就是封裝變化。識(shí)別系統(tǒng)中可能的不穩(wěn)定或者變化,在不穩(wěn)定組件上創(chuàng)建穩(wěn)定的抽象接口,將可能的變化封裝在接口之后,使得系統(tǒng)內(nèi)部的不穩(wěn)定或者變化不會(huì)對(duì)系統(tǒng)的其它部分產(chǎn)生不良影響。
SOLID 面向?qū)ο笤O(shè)計(jì)原則
S.O.L.I.D 是面向?qū)ο笤O(shè)計(jì)和編程 (OOD&OOP) 中幾個(gè)重要原則的首字母縮寫(xiě),受 Robert Martin 推崇。
1. 單一職責(zé)原則 (The Single Responsibility Principle)
修改某個(gè)類(lèi)的理由應(yīng)該只有一個(gè),如果超過(guò)一個(gè),說(shuō)明類(lèi)承擔(dān)不止一個(gè)職責(zé),要視情況拆分。
2. 開(kāi)放封閉原則 (The Open Closed Principle)
軟件實(shí)體應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改封閉。一般不要直接修改類(lèi)庫(kù)源碼(即使你有源代碼),通過(guò)繼承等方式擴(kuò)展。
3. 里氏替代原則 (The Liskov Substitution Principle)
當(dāng)一個(gè)子類(lèi)的實(shí)例能夠被替換成任何超類(lèi)的實(shí)例時(shí),它們之間才是真正的 is-a 關(guān)系。
4. 依賴(lài)倒置原則 (The Dependency Inversion Principle)
高層模塊不應(yīng)該依賴(lài)于底層模塊,二者都應(yīng)該依賴(lài)于抽象。換句話(huà)說(shuō),依賴(lài)于抽象,不要依賴(lài)于具體實(shí)現(xiàn)。比方說(shuō),你不會(huì)把電器電源線焊死在室內(nèi)電源接口處,而是用標(biāo)準(zhǔn)的插頭插在標(biāo)準(zhǔn)的插座 (抽象) 上。
5. 接口分離原則 (The Interface Segregation Principle)
不要強(qiáng)迫用戶(hù)去依賴(lài)它們不使用的接口。換句話(huà)說(shuō),使用多個(gè)專(zhuān)門(mén)的接口比使用單一的大而全接口要好。
我的解讀
我職業(yè)早年主要關(guān)注軟件設(shè)計(jì)和編程,所以花蠻多時(shí)間學(xué)習(xí)和消化 GRASP 和 SOLID 設(shè)計(jì)原則。這些原則對(duì)我影響很深,尤其是單一職責(zé),信息專(zhuān)家,關(guān)注分離,依賴(lài)倒置 / 封裝變化,分而治之等核心原則,現(xiàn)在日常研發(fā)中我時(shí)常用這些原則指導(dǎo)新手工程師。高內(nèi)聚 + 低耦合,就像道中的一陰一陽(yáng),是所有其它 OO 設(shè)計(jì)原則的原則 (元原則),其它設(shè)計(jì)原則都是在這兩個(gè)基礎(chǔ)上泛化衍生出來(lái)的。上述原則雖然是針對(duì) OO 設(shè)計(jì)和編程提出,但是對(duì)于大規(guī)模系統(tǒng)架構(gòu)仍然適用。比如,微服務(wù)架構(gòu)就體現(xiàn)了:?jiǎn)我宦氊?zé):一個(gè)微服務(wù)盡可能要職責(zé)單一,提供的接口也盡可能單一 (接口分離原則),安全 / 路由 / 限流等跨橫切面的關(guān)注點(diǎn) (Cross-Cutting Concerns) 由獨(dú)立網(wǎng)關(guān)負(fù)責(zé),體現(xiàn)關(guān)注分離 (Separation of Concerns)。信息專(zhuān)家:當(dāng)不確定哪個(gè)團(tuán)隊(duì)?wèi)?yīng)該負(fù)責(zé)某個(gè)微服務(wù)時(shí),一般原則也是誰(shuí)擁有數(shù)據(jù)誰(shuí)負(fù)責(zé),基于有界上下文 Bounded Context(一般是邊界比較清晰的領(lǐng)域數(shù)據(jù)源)構(gòu)建微服務(wù)。松散耦合:服務(wù)之間通過(guò) HTTP/JSON 等輕量機(jī)制通信,服務(wù)之間不強(qiáng)耦合。受保護(hù)的變化和依賴(lài)倒置:服務(wù)之間只依賴(lài)抽象接口,實(shí)現(xiàn)可能隨時(shí)變化。間接:網(wǎng)關(guān)在外面的客戶(hù)端和內(nèi)部的服務(wù)之間增加了一層間接,使兩者不強(qiáng)耦合,可以相互獨(dú)立演化。作為架構(gòu)師或者設(shè)計(jì)師,有兩個(gè)設(shè)計(jì)能力是需要重點(diǎn)培養(yǎng)的,也是最難和最能體現(xiàn)架構(gòu)設(shè)計(jì)水平的:合理的職責(zé)分配能力,也就是每個(gè)類(lèi) / 組件 / 子系統(tǒng)應(yīng)該承擔(dān)什么職責(zé),如何保證職責(zé)單一,它們之間如何協(xié)作;系統(tǒng)抽象和核心領(lǐng)域建模能力,需要深入一線業(yè)務(wù)域。
分布式系統(tǒng)架構(gòu)設(shè)計(jì)原則和理論AKF 架構(gòu)原則
這 15 個(gè)架構(gòu)原則來(lái)自《架構(gòu)即未來(lái) (The Art of Scalability)》[附錄 2] 一書(shū),作者馬丁 L. 阿伯特和邁克爾 T. 費(fèi)舍爾分別是 eBay 和 PayPal 的前 CTO,他們經(jīng)歷過(guò) eBay 和 PayPal 大規(guī)模分布式電商平臺(tái)的架構(gòu)演進(jìn),在一線實(shí)戰(zhàn)經(jīng)驗(yàn)的基礎(chǔ)上總結(jié)并提煉出 15 條架構(gòu)原則:
1.N + 1 設(shè)計(jì)
永遠(yuǎn)不要少于兩個(gè),通常為三個(gè)。比方說(shuō)無(wú)狀態(tài)的 Web/API 一般部署至少>=2 個(gè)。
2. 回滾設(shè)計(jì)
確保系統(tǒng)可以回滾到以前發(fā)布過(guò)的任何版本??梢酝ㄟ^(guò)發(fā)布系統(tǒng)保留歷史版本,或者代碼中引入動(dòng)態(tài)開(kāi)關(guān)切換機(jī)制 (Feature Switch)。
3. 禁用設(shè)計(jì)
能夠關(guān)閉任何發(fā)布的功能。新功能隱藏在動(dòng)態(tài)開(kāi)關(guān)機(jī)制 (Feature Switch) 后面,可以按需一鍵打開(kāi),如發(fā)現(xiàn)問(wèn)題隨時(shí)關(guān)閉禁用。
4. 監(jiān)控設(shè)計(jì)
在設(shè)計(jì)階段就必須考慮監(jiān)控,而不是在實(shí)施完畢之后補(bǔ)充。例如在需求階段就要考慮關(guān)鍵指標(biāo)監(jiān)控項(xiàng),這就是度量驅(qū)動(dòng)開(kāi)發(fā) (Metrics Driven Development) 的理念。
5. 設(shè)計(jì)多活數(shù)據(jù)中心
不要被一個(gè)數(shù)據(jù)中心的解決方案把自己限制住。當(dāng)然也要考慮成本和公司規(guī)模發(fā)展階段。
6. 使用成熟的技術(shù)
只用確實(shí)好用的技術(shù)。商業(yè)組織畢竟不是研究機(jī)構(gòu),技術(shù)要落地實(shí)用,成熟的技術(shù)一般坑都被踩平了,新技術(shù)在完全成熟前一般需要踩坑躺坑。
7. 異步設(shè)計(jì)
能異步盡量用異步,只有當(dāng)絕對(duì)必要或者無(wú)法異步時(shí),才使用同步調(diào)用。
8. 無(wú)狀態(tài)系統(tǒng)
盡可能無(wú)狀態(tài),只有當(dāng)業(yè)務(wù)確實(shí)需要,才使用狀態(tài)。無(wú)狀態(tài)系統(tǒng)易于擴(kuò)展,有狀態(tài)系統(tǒng)不易擴(kuò)展且狀態(tài)復(fù)雜時(shí)更易出錯(cuò)。
9. 水平擴(kuò)展而非垂直升級(jí)
永遠(yuǎn)不要依賴(lài)更大、更快的系統(tǒng)。一般公司成長(zhǎng)到一定階段普遍經(jīng)歷過(guò)買(mǎi)更大、更快系統(tǒng)的階段,即使淘寶當(dāng)年也買(mǎi)小型機(jī)扛流量,后來(lái)扛不住才體會(huì)這樣做不 scalable,所以才有后來(lái)的去 IOE 行動(dòng)。
10. 設(shè)計(jì)時(shí)至少要有兩步前瞻性
在擴(kuò)展性問(wèn)題發(fā)生前考慮好下一步的行動(dòng)計(jì)劃。架構(gòu)師的價(jià)值就體現(xiàn)在這里,架構(gòu)設(shè)計(jì)對(duì)于流量的增長(zhǎng)要有提前量。
11. 非核心則購(gòu)買(mǎi)
如果不是你最擅長(zhǎng),也提供不了差異化的競(jìng)爭(zhēng)優(yōu)勢(shì)則直接購(gòu)買(mǎi)。避免 Not Invented Here 癥狀,避免凡事都要重造輪子,畢竟達(dá)成業(yè)務(wù)目標(biāo)才是重點(diǎn)。
12. 使用商品化硬件
在大多數(shù)情況下,便宜的就是最好的。這點(diǎn)和第 9 點(diǎn)是一致的,通過(guò)商品化硬件水平擴(kuò)展,而不是買(mǎi)更大、更快的系統(tǒng)。
13. 小構(gòu)建、小發(fā)布和快試錯(cuò)
全部研發(fā)要小構(gòu)建,不斷迭代,讓系統(tǒng)不斷成長(zhǎng)。這個(gè)和微服務(wù)理念一致。
14. 隔離故障
實(shí)現(xiàn)故障隔離設(shè)計(jì),通過(guò)斷路保護(hù)避免故障傳播和交叉影響。通過(guò)艙壁泳道等機(jī)制隔離失敗單元 (Failure Unit),一個(gè)單元的失敗不至影響其它單元的正常工作。
15. 自動(dòng)化
設(shè)計(jì)和構(gòu)建自動(dòng)化的過(guò)程。如果機(jī)器可以做,就不要依賴(lài)于人。自動(dòng)化是 DevOps 的基礎(chǔ)。
我的解讀
這 15 條架構(gòu)原則基本上是 eBay 在發(fā)展,經(jīng)歷過(guò)流量數(shù)量級(jí)增長(zhǎng)沖擊過(guò)程中,通過(guò)不斷踩坑踩出來(lái)的,是干貨中的干貨。消化吸收這 15 條原則,基本可保系統(tǒng)架構(gòu)不會(huì)有原則性問(wèn)題。這 15 條原則同樣適用于現(xiàn)在的微服務(wù)架構(gòu)。eBay 發(fā)展較早,它內(nèi)部其實(shí)很早 (差不多 2010 年前) 就已形成完善的微服務(wù)生態(tài),只是沒(méi)有提出微服務(wù)這個(gè)概念。這 15 條原則可根據(jù) TTM(Time To Market),可用性 / 可擴(kuò)展性 / 質(zhì)量,成本 / 效率分布在三個(gè)環(huán)內(nèi),如下圖所示。
12 要素應(yīng)用
Heroku[附錄 3] 是國(guó)外知名的云應(yīng)用平臺(tái)?;谏习偃f(wàn)應(yīng)用的托管和運(yùn)營(yíng)經(jīng)驗(yàn),創(chuàng)始人 Adam Wiggins 提出了 12 要素應(yīng)用宣言 [附錄 4]。簡(jiǎn)單講,滿(mǎn)足這 12 個(gè)要素的應(yīng)用是比較容易云化并居住在 Heroku 平臺(tái)上的。
1. 基準(zhǔn)代碼
一份基準(zhǔn)代碼,多份部署。如果用鏡像部署方式,則一個(gè)鏡像可以部署到多個(gè)環(huán)境 (測(cè)試,預(yù)發(fā),生產(chǎn)),而不是給每個(gè)環(huán)境制作一個(gè)不同鏡像。
2. 依賴(lài)
顯式聲明依賴(lài)。如果用鏡像部署,則一般依賴(lài)被直接打在鏡像中,或者聲明在 docker file 中。
3. 配置
在環(huán)境中存儲(chǔ)配置。在 Heroku 或者類(lèi)似的 PaaS 平臺(tái)上,配置一般是推薦注入到環(huán)境變量中的?,F(xiàn)在采用集中式配置中心也是一種流行方式。
4. 后端服務(wù)
把后端服務(wù) (例如緩存,數(shù)據(jù)庫(kù),MQ 等) 當(dāng)作附加資源,相關(guān)配置和連接字符串通過(guò)環(huán)境變量注入,或者采用配置中心。
5. 構(gòu)建、發(fā)布和運(yùn)行
嚴(yán)格分離構(gòu)建和運(yùn)行。如果使用鏡像部署,則構(gòu)建、發(fā)布 / 運(yùn)行是通過(guò)鏡像這種中間格式嚴(yán)格分離的。
6. 進(jìn)程
一個(gè)或者多個(gè)無(wú)狀態(tài)的進(jìn)程運(yùn)行應(yīng)用。容器運(yùn)行時(shí)相當(dāng)于進(jìn)程,適用于無(wú)狀態(tài) Web/API。
7. 端口綁定
通過(guò)端口綁定提供服務(wù)。容器也是通過(guò)端口綁定對(duì)外提供服務(wù)。
8. 并發(fā)
通過(guò)進(jìn)程模型進(jìn)行擴(kuò)展。容器運(yùn)行時(shí)相當(dāng)于進(jìn)程,通過(guò)起多個(gè)容器可以任意擴(kuò)展并發(fā)數(shù)量。
9. 易處理
快速啟動(dòng)和優(yōu)雅終止可最大化健壯性。docker 容器支持秒級(jí)啟動(dòng)和關(guān)閉。
10. 開(kāi)發(fā)環(huán)境和線上環(huán)境等價(jià)
盡可能保持開(kāi)發(fā)、測(cè)試、預(yù)發(fā)和線上環(huán)境相同。容器可以保證容器內(nèi)運(yùn)行時(shí)環(huán)境的一致性,還需要保證不同環(huán)境的一致性,例如不同環(huán)境內(nèi)的操作系統(tǒng),負(fù)載均衡,服務(wù)發(fā)現(xiàn),后臺(tái)服務(wù),監(jiān)控告警等要盡可能一致。
11. 日志
把日志當(dāng)作數(shù)據(jù)流。Heroku 不支持本地文件,所以必須以流方式把日志輸送到后臺(tái)日志服務(wù)。除了日志以外還要補(bǔ)充考慮 metrics 流的采集和輸送。
12. 管理進(jìn)程
后臺(tái)管理任務(wù)當(dāng)作一次性的進(jìn)程。其實(shí)相當(dāng)于在 Heroku 上以獨(dú)立進(jìn)程方式運(yùn)行任務(wù) Job。
我的解讀
12 要素應(yīng)用也是當(dāng)前云原生應(yīng)用 (Cloud Native App) 的參考標(biāo)準(zhǔn),我把這 12 要素也稱(chēng)為云應(yīng)用遷移原則。滿(mǎn)足這 12 個(gè)要素的應(yīng)用,可以比較順利遷移到各種云平臺(tái) (Kubernetes, Marathon, Cloud Foundry 等) 上。對(duì)于面臨企業(yè)遺留應(yīng)用改造和云化遷移的架構(gòu)師,可以重點(diǎn)參考這 12 條遷移原則。Docker 容器技術(shù)可以認(rèn)為是為云遷移量身定制的技術(shù)。容器化是后續(xù)云遷移的捷徑,所以遺留應(yīng)用改造可以先想辦法做到容器化。
CAP 定理
2000 年 7 月,加州大學(xué)伯克利分校的 Eric Brewer 教授在 ACM PODC 會(huì)議上提出 CAP 猜想。2 年后,麻省理工學(xué)院的 Seth Gilbert 和 Nancy Lynch 從理論上證明了 CAP。之后,CAP 理論正式成為分布式計(jì)算領(lǐng)域的公認(rèn)定理。
CAP 認(rèn)為:一個(gè)分布式系統(tǒng)最多同時(shí)滿(mǎn)足一致性 (Consistency),可用性 (Availability) 和分區(qū)容忍性 (Partition Tolerance) 這三項(xiàng)中的兩項(xiàng)。
1.一致性 (Consistency)
一致性指“all nodes see the same data at the same time”,即更新操作成功,所有節(jié)點(diǎn)在同一時(shí)間的數(shù)據(jù)完全一致。
2.可用性 (Availability)
可用性指“Reads and writes always succeed”,即服務(wù)一直可用,而且響應(yīng)時(shí)間正常。
3.分區(qū)容忍性 (Partition tolerance)
分區(qū)容忍性指“the system continue to operate despite arbitrary message loss or failure of part of the system.”,即分布式系統(tǒng)在遇到某節(jié)點(diǎn)或網(wǎng)絡(luò)分區(qū)故障時(shí),仍然能夠?qū)ν馓峁M(mǎn)足一致性和可用性的服務(wù)。
BASE...