架構(gòu)篇:什么才是真正的架構(gòu)設(shè)計(jì)?

劇照 | 《艾米麗在巴黎》
一. 什么是架構(gòu)和架構(gòu)本質(zhì)
在軟件行業(yè),對于什么是架構(gòu),都有很多的爭論,每個人都有自己的理解。此君說的架構(gòu)和彼君理解的架構(gòu)未必是一回事。因此我們在討論架構(gòu)之前,我們先討論架構(gòu)的概念定義,概念是人認(rèn)識這個世界的基礎(chǔ),并用來溝通的手段,如果對架構(gòu)概念理解不一樣,那溝通起來自然不順暢。
系統(tǒng):泛指由一群有關(guān)聯(lián)的個體組成,根據(jù)某種規(guī)則運(yùn)作,能完成個別元件不能獨(dú)立完成的工作能力的群體。
子系統(tǒng):也是由一群關(guān)聯(lián)的個體組成的系統(tǒng),多半是在更大的系統(tǒng)中的一部分。
1.2. 模塊與組件
1.3. 框架與架構(gòu)
系統(tǒng)性思考的合理決策:比如技術(shù)選型、解決方案等。 明確的系統(tǒng)骨架:明確系統(tǒng)有哪些部分組成。 系統(tǒng)協(xié)作關(guān)系:各個組成部分如何協(xié)作來實(shí)現(xiàn)業(yè)務(wù)請求。 約束規(guī)范和指導(dǎo)原則:保證系統(tǒng)有序,高效、穩(wěn)定運(yùn)行。
因此架構(gòu)師具備能力:理解業(yè)務(wù),全局把控,選擇合適技術(shù),解決關(guān)鍵問題、指導(dǎo)研發(fā)落地實(shí)施。
架構(gòu)的本質(zhì)就是對系統(tǒng)進(jìn)行有序化地重構(gòu)以致符合當(dāng)前業(yè)務(wù)的發(fā)展,并可以快速擴(kuò)展。
那什么樣的系統(tǒng)要考慮做架構(gòu)設(shè)計(jì) 技術(shù)不會平白無故的出和自驅(qū)動發(fā)展起來,而架構(gòu)的發(fā)展和需求是基于業(yè)務(wù)的驅(qū)動。
架構(gòu)設(shè)計(jì)完全是為了業(yè)務(wù),
需求相對復(fù)雜. 非功能性需求在整個系統(tǒng)占據(jù)重要位置. 系統(tǒng)生命周期長,有擴(kuò)展性需求. 系統(tǒng)基于組件或者集成的需要. 業(yè)務(wù)流程再造的需要.
二. 架構(gòu)分層和分類

2.1. 業(yè)務(wù)架構(gòu)(俯視架構(gòu)):

2.2. 應(yīng)用架構(gòu)(剖面架構(gòu),也叫邏輯架構(gòu)圖):

邏輯分層 子系統(tǒng)、模塊定義。 關(guān)鍵類。
接口協(xié)議:應(yīng)用對外輸出的接口。 協(xié)作關(guān)系:應(yīng)用之間的調(diào)用關(guān)系。
一種是水平分(橫向),按照功能處理順序劃分應(yīng)用,比如把系統(tǒng)分為web前端/中間服務(wù)/后臺任務(wù),這是面向業(yè)務(wù)深度的劃分。 另一種是垂直分(縱向),按照不同的業(yè)務(wù)類型劃分應(yīng)用,比如進(jìn)銷存系統(tǒng)可以劃分為三個獨(dú)立的應(yīng)用,這是面向業(yè)務(wù)廣度的劃分。

配置設(shè)計(jì) 框架、類庫。
編碼規(guī)范,編碼的慣例。 項(xiàng)目模塊劃分 頂層文件結(jié)構(gòu)設(shè)計(jì),比如mvc設(shè)計(jì)。 依賴關(guān)系

2.6. 部署拓?fù)浼軜?gòu)圖(實(shí)際物理架構(gòu)圖):


三. 架構(gòu)級別

系統(tǒng)級:即整個系統(tǒng)內(nèi)各部分的關(guān)系以及如何治理:分層 應(yīng)用級:即單個應(yīng)用的整體架構(gòu),及其與系統(tǒng)內(nèi)單個應(yīng)用的關(guān)系等。 模塊級:即應(yīng)用內(nèi)部的模塊架構(gòu),如代碼的模塊化、數(shù)據(jù)和狀態(tài)的管理等。 代碼級:即從代碼級別保障架構(gòu)實(shí)施。
戰(zhàn)略設(shè)計(jì):業(yè)務(wù)架構(gòu)用于指導(dǎo)架構(gòu)師如何進(jìn)行系統(tǒng)架構(gòu)設(shè)計(jì)。 戰(zhàn)術(shù)設(shè)計(jì):應(yīng)用架構(gòu)要根據(jù)業(yè)務(wù)架構(gòu)來設(shè)計(jì)。 戰(zhàn)術(shù)實(shí)施:應(yīng)用架構(gòu)確定以后,就是技術(shù)選型。

四. 應(yīng)用架構(gòu)演進(jìn)


性能需求:使用緩存改善性能 并發(fā)需求:使用集群改善并發(fā) 讀寫分離:數(shù)據(jù)庫地讀寫分離 使用反向代理和cdn加速 使用分布式文件和分布式數(shù)據(jù)庫
復(fù)雜性高:以一個百萬行級別的單體應(yīng)用為例,整個項(xiàng)目包含的模塊非常多、模塊的邊界模糊、 依賴關(guān)系不清晰、 代碼質(zhì)量參差不齊、 混亂地堆砌在一起。可想而知整個項(xiàng)目非常復(fù)雜。每次修改代碼都心驚膽戰(zhàn), 甚至添加一個簡單的功能, 或者修改一個Bug都會帶來隱含的缺陷。
技術(shù)債務(wù):隨著時間推移、需求變更和人員更迭,會逐漸形成應(yīng)用程序的技術(shù)債務(wù), 并且越積 越多。“ 不壞不修”, 這在軟件開發(fā)中非常常見, 在單體應(yīng)用中這種思想更甚。已使用的系統(tǒng)設(shè)計(jì)或代碼難以被修改,因?yàn)閼?yīng)用程序中的其他模塊可能會以意料之外的方式使用它。
部署頻率低:隨著代碼的增多,構(gòu)建和部署的時間也會增加。而在單體應(yīng)用中, 每次功能的變更或缺陷的修復(fù)都會導(dǎo)致需要重新部署整個應(yīng)用。全量部署的方式耗時長、 影響范圍大、 風(fēng)險(xiǎn)高, 這使得單體應(yīng)用項(xiàng)目上線部署的頻率較低。而部署頻率低又導(dǎo)致兩次發(fā)布之間會有大量的功能變更和缺陷修復(fù),出錯率比較高。
可靠性差:某個應(yīng)用Bug,例如死循環(huán)、內(nèi)存溢出等, 可能會導(dǎo)致整個應(yīng)用的崩潰。
擴(kuò)展能力受限:單體應(yīng)用只能作為一個整體進(jìn)行擴(kuò)展,無法根據(jù)業(yè)務(wù)模塊的需要進(jìn)行伸縮。例如,應(yīng)用中有的模塊是計(jì)算密集型的,它需要強(qiáng)勁的CPU;有的模塊則是IO密集型的,需要更大的內(nèi)存。由于這些模塊部署在一起,不得不在硬件的選擇上做出妥協(xié)。
阻礙技術(shù)創(chuàng)新:單體應(yīng)用往往使用統(tǒng)一的技術(shù)平臺或方案解決所有的問題, 團(tuán)隊(duì)中的每個成員 都必須使用相同的開發(fā)語言和框架,要想引入新框架或新技術(shù)平臺會非常困難。
降低了耦合度:把模塊拆分,使用接口通信,降低模塊之間的耦合度。
責(zé)任清晰:把項(xiàng)目拆分成若干個子項(xiàng)目,不同的團(tuán)隊(duì)負(fù)責(zé)不同的子項(xiàng)目。
擴(kuò)展方便:增加功能時只需要再增加一個子項(xiàng)目,調(diào)用其他系統(tǒng)的接口就可以。
部署方便:可以靈活的進(jìn)行分布式部署。
提高代碼的復(fù)用性:比如Service層,如果不采用分布式rest服務(wù)方式架構(gòu)就會在手機(jī)Wap商城,微信商城,PC,Android,iOS每個端都要寫一個Service層邏輯,開發(fā)量大,難以維護(hù)一起升級,這時候就可以采用分布式rest服務(wù)方式,公用一個service層。
缺點(diǎn):系統(tǒng)之間的交互要使用遠(yuǎn)程通信,接口開發(fā)增大工作量,但是利大于弊。
易于開發(fā)和維護(hù):一個微服務(wù)只會關(guān)注一個特定的業(yè)務(wù)功能,所以它業(yè)務(wù)清晰、代碼量較少。開發(fā)和維護(hù)單個微服務(wù)相對簡單。而整個應(yīng)用是由若干個微服務(wù)構(gòu)建而成的,所以整個應(yīng)用也會被維持在一個可控狀態(tài)。
單個微服務(wù)啟動較快:單個微服務(wù)代碼量較少, 所以啟動會比較快。
局部修改容易部署:單體應(yīng)用只要有修改,就得重新部署整個應(yīng)用,微服務(wù)解決了這樣的問題。一般來說,對某個微服務(wù)進(jìn)行修改,只需要重新部署這個服務(wù)即可。
技術(shù)棧不受限:在微服務(wù)架構(gòu)中,可以結(jié)合項(xiàng)目業(yè)務(wù)及團(tuán)隊(duì)的特點(diǎn),合理地選擇技術(shù)棧。例如某些服務(wù)可使用關(guān)系型數(shù)據(jù)庫MySQL;某些微服務(wù)有圖形計(jì)算的需求,可以使用Neo4j;甚至可根據(jù)需要,部分微服務(wù)使用Java開發(fā),部分微服務(wù)使用Node.js開發(fā)。
運(yùn)維要求較高:更多的服務(wù)意味著更多的運(yùn)維投入。在單體架構(gòu)中,只需要保證一個應(yīng)用的正常運(yùn)行。而在微服務(wù)中,需要保證幾十甚至幾百個服務(wù)服務(wù)的正常運(yùn)行與協(xié)作,這給運(yùn)維帶來了很大的挑戰(zhàn)。
分布式固有的復(fù)雜性:使用微服務(wù)構(gòu)建的是分布式系統(tǒng)。對于一個分布式系統(tǒng),系統(tǒng)容錯、網(wǎng)絡(luò)延遲、分布式事務(wù)等都會帶來巨大的挑戰(zhàn)。
接口調(diào)整成本高:微服務(wù)之間通過接口進(jìn)行通信。如果修改某一個微服務(wù)的API,可能所有使用了該接口的微服務(wù)都需要做調(diào)整。
重復(fù)勞動:很多服務(wù)可能都會使用到相同的功能,而這個功能并沒有達(dá)到分解為一個微服務(wù)的程度,這個時候,可能各個服務(wù)都會開發(fā)這一功能,從而導(dǎo)致代碼重復(fù)。盡管可以使用共享庫來解決這個問題(例如可以將這個功能封裝成公共組件,需要該功能的微服務(wù)引用該組件),但共享庫在多語言環(huán)境下就不一定行得通了。
五. 衡量架構(gòu)的合理性
能解決當(dāng)下業(yè)務(wù)需求和問題 高效完成業(yè)務(wù)需求: 能以優(yōu)雅且可復(fù)用的方式解決當(dāng)下所有業(yè)務(wù)問題 前瞻性設(shè)計(jì): 能在未來一段時間都能以第2種方式滿足業(yè)務(wù),從而不會每次當(dāng)業(yè)務(wù)進(jìn)行演變時,導(dǎo)致架構(gòu)翻天覆地的變化。
5.2. 非業(yè)務(wù)需求角度
高可用:要盡可能的提高軟件的可用性,我想每個操作人都不愿意看到自己的工作無法正常進(jìn)行。黑盒白盒測試、單元測試、自動化測試、故障注入測試、提高測試覆蓋率等方式來一步一步推進(jìn)。
文檔化:不管是整體還是部分的整個生命周期內(nèi)都必須做好文檔化,變動的來源包括但不限于BUG,需求。 可擴(kuò)展:軟件的設(shè)計(jì)秉承著低耦合的理念去做,注意在合理的地方抽象。方便功能更改、新增和運(yùn)用技術(shù)的迭代,并且支持在適時對架構(gòu)做出重構(gòu)。 高復(fù)用:為了避免重復(fù)勞動,為了降低成本,我們希望能夠重用之前的代碼、之前的設(shè)計(jì)。這點(diǎn)對于架構(gòu)環(huán)境的依賴是最大的。
安全:組織的運(yùn)作過程中產(chǎn)生的數(shù)據(jù)都是具有商業(yè)價(jià)值的,保證數(shù)據(jù)的安全也是刻不容緩的一部分。以免出現(xiàn)XX門之類丑聞。加密、https等為普遍手段
六. 常見架構(gòu)誤區(qū)
開高走落不到實(shí)處
遺漏關(guān)鍵性約束與非功能需求 為虛無的未來埋單而過度設(shè)計(jì) 過早做出關(guān)鍵性決策 客戶說啥就是啥成為傳話筒 埋頭干活兒缺乏前瞻性 架構(gòu)設(shè)計(jì)還要考慮系統(tǒng)可測性 架構(gòu)設(shè)計(jì)不要企圖一步到位
誤區(qū)1——架構(gòu)專門由架構(gòu)師來做,業(yè)務(wù)開發(fā)人員無需關(guān)注:架構(gòu)的再好,最終還是需要代碼來落地,并且組織越大這個落地的難度越大。不單單是系統(tǒng)架構(gòu),每個解決方案每個項(xiàng)目也由自己的架構(gòu),如分層、設(shè)計(jì)模式等。如果每一塊磚瓦不夠堅(jiān)固,那么整個系統(tǒng)還是會由崩塌的風(fēng)險(xiǎn)。所謂“千里之堤,潰于蟻穴”。 誤區(qū)2——架構(gòu)師確定了架構(gòu)藍(lán)圖之后任務(wù)就結(jié)束了:架構(gòu)不是“空中樓閣”,最終還是要落地的,但是架構(gòu)師完全不去深入到第一線怎么知道“地”在哪?怎么才能落的穩(wěn)穩(wěn)當(dāng)當(dāng)。 誤區(qū)3——不做出完美的架構(gòu)設(shè)計(jì)不開工:世上沒有最好架構(gòu),只有最合適的架構(gòu),不要企圖一步到位。我們需要的不是一下子造出一輛汽車,而是從單輪車→自行車→摩托車,最后再到汽車。想象一下2年后才能造出的產(chǎn)品,當(dāng)初市場還存在嗎? 誤區(qū)4—— 為虛無的未來埋單而過度設(shè)計(jì):在創(chuàng)業(yè)公司初期,業(yè)務(wù)場景和需求邊界很難把握,產(chǎn)品需要快速迭代和變現(xiàn),需求頻繁更新,這個時候需要的是快速實(shí)現(xiàn)。不要過多考慮未來的擴(kuò)展,說不定功能做完,效果不好就無用了。如果業(yè)務(wù)模式和應(yīng)用場景邊界都已經(jīng)比較清晰,是應(yīng)該適當(dāng)?shù)目紤]未來的擴(kuò)展性設(shè)計(jì)。 誤區(qū)5——一味追隨大公司的解決方案:由于大公司巨大成功的光環(huán)效應(yīng),再加上從大公司挖來的技術(shù)高手的影響,網(wǎng)站在討論架構(gòu)決策時,最有說服力的一句話就成了“淘寶就是這么搞的”或者“騰訊 就是這么搞的”。大公司的經(jīng)驗(yàn)和成功模式固然重要,值得學(xué)習(xí)借鑒,但如果因此而變得盲從,就失去了堅(jiān)持自我的勇氣,在架構(gòu)演化的道路上遲早會迷路。 誤區(qū)6——為了技術(shù)而技術(shù):技術(shù)是為業(yè)務(wù)而存在的,除此毫無意義。在技術(shù)選型和架構(gòu)設(shè)計(jì)中,脫離網(wǎng)站業(yè)務(wù)發(fā)展的實(shí)際,一味追求時髦的新技術(shù),可能會將技術(shù)發(fā)展引入崎嶇小道,架構(gòu)之路越走越難。考慮實(shí)現(xiàn)成本、時間、人員等各方面都要綜合考慮,理想與現(xiàn)實(shí)需要折中。
七. 架構(gòu)知識體系
初始階段:LAMP,部署在一臺服務(wù)器 應(yīng)用服務(wù)器和數(shù)據(jù)服務(wù)器分離 使用緩存改善性能 使用集群改善并發(fā) 數(shù)據(jù)庫地讀寫分離 使用反向代理和cdn加速 使用分布式文件和分布式數(shù)據(jù)庫 業(yè)務(wù)拆分 分布式服務(wù)
分布式應(yīng)用和服務(wù) 分布式靜態(tài)資源 分布式數(shù)據(jù)和存儲 分布式計(jì)算
cdn 方向代理訪問資源 本地緩存 分布式緩存
提供系統(tǒng)的可用性 加快響應(yīng)速度
性能測試 前端優(yōu)化 應(yīng)用優(yōu)化 數(shù)據(jù)庫優(yōu)化
負(fù)載均衡 數(shù)據(jù)備份 自動發(fā)布 灰度發(fā)布 監(jiān)控報(bào)警
負(fù)載均衡 緩存負(fù)載均衡
分布式消息 服務(wù)化
xss攻擊 sql注入 csr攻擊 web防火墻漏洞 安全漏洞 ssl
八. 架構(gòu)書籍推薦
大多數(shù)時候所謂的“技術(shù)之玻璃天花板”其實(shí)只是缺乏軟技能而已。這些技能可以學(xué)到,缺乏的知識可以通過決定改變的努力來彌補(bǔ)。

近期熱門文章推薦:

