01 架構=要素+結構+連接
在軟件行業,對于什么是架構一直有很多的爭論,每個人都有自己的理解。不同的書籍上、不同的作者,對于架構的定義也不統一,角度不同,定義不同。此君說的架構和彼君理解的架構未必是一回事。
因此我們在討論架構之前,我們先討論架構的概念定義,因為概念是人認識這個世界的基礎和用來溝通的手段,如果對架構概念理解不一樣,那溝通起來自然不順暢。
Linux 有架構,MySQL 有架構,JVM 也有架構,使用 Java 開發、MySQL 存儲、跑在 Linux 上的業務系統也有架構,應該關注哪一個?想要清楚以上問題需要梳理幾個有關系又相似的概念:系統與子系統、模塊與組建、框架與架構。
???1.1??系統與子系統?
系統:泛指由一群有關聯的個體組成,根據某種規則運作,能完成個別元件不能獨立完成的工作能力的群體。提到系統,我們務必了解以下幾個關鍵詞:
關聯:系統是由一群有關聯的個體組成的,沒有關聯的個體堆在一起不能成為一個系統。例如,把一個發動機和一臺 PC 放在一起不能稱之為一個系統,把發動機、底盤、輪胎、車架組合起來才能成為一臺汽車。
規則:系統內的個體需要按照指定的規則運作,而不是單個個個體各自為政。規則規定了系統內個體分工和協作的方式。例如,汽車發動機負責產生動力,然后通過變速器和傳動軸,將動力輸出到車輪上,從而驅動汽車前進。
能力:系統能力與個體能力有本質的差別,系統能力不是個體能力之和,而是產生了新的能力。例如,汽車能夠載重前進,而發動機、變速器、傳動軸、車輪本身都不具備這樣的能力。
子系統:也是由一群關聯的個體組成的系統,多半是在更大的系統中的一部分。
???1.2?模塊與組件?
它們都是系統的組成部分,從不同角度拆分系統而已。模塊是邏輯單元,組件是物理單元。
模塊就是從邏輯上將系統分解, 即分而治之, 將復雜問題簡單化。模塊的粒度可大可小, 可以是系統、幾個子系統、某個服務、函數、類、方法、 功能塊等等。劃分模塊的主要目的是職責分離。
組件可以包括應用服務、數據庫、網絡、物理機,還可以包括 MQ、容器、Nginx 等技術組件。劃分組件的主要目的是單元復用。“組件”的英文單詞 Component,對應中文的“零件”一詞,“零件”更容易理解一些。“零件”是一個物理的概念,并且具備“獨立且可替換”的特點。現在越來越被的 UI 設計使用組件化和模塊化。
???1.3?框架與架構?
框架通常指的是為了實現某個業界標準或完成特定基本任務的軟件組件規范,也指為了實現某個軟件組件規范時,提供規范所要求之基礎功能的軟件產品。
框架是組件實現的規范,例如:MVC、MVP、MVVM 等,是提供基礎功能的產品,例如開源框架:Ruby on Rails、Spring、Laravel、Django 等,這是可以拿來直接使用或者在此基礎上二次開發。
再例如,SpringMVC 是 MVC 的開發框架,除了滿足 MVC 的規范,Spring 提供了很多基礎功能來幫助我們實現功能,包括注解(@Controller等)、Spring Security、SpringJPA 等很多基礎功能。
框架是規范,架構是結構。
框架和架構的區別還是比較明顯的,框架關注的是“規范”,架構關注的是“結構”。框架的英文是 Framework 。例如,SpringMVC 是"Web MVC Framework"。架構的英文是 Architecture。例如,Linux 操作系統的架構。
在 TOGAF9 是這么定義:一個系統基本的構件(子系統,模塊,組件),體現在它的各個構件、構件間的相互關系、構件與環境間的關系,以及對系統設計和演進進行治理的原則中。
兩種含義:
???第一,一個系統的形式化描述,或指導系統實現的構件級的詳細計劃。
???第二,一組構件的結構、構件間的相互關系,以及對這些構件的設計和隨時間演進的過程進行治理的一些原則和指導策略。
架構從字面意思上,是源于古代的建筑術語。
把架構拆分成兩個字“架”和“構”。“架”就是“加”和“木”的結合,把木頭加起來、連接起來就是架。“構”就是結構的意思。所以,“架構”就是把“木”按照一定的結構連接起來。
對應到軟件架構,“木”代表構件(要素),“結構”代表架構的產物:木就是系統中的要素,我們將它們稱之為架構構件(要素)。架構要素可以是子系統、模塊、應用服務、組件。結構,是架構的產物。不同的軟件系統會有不同的結構,這些結構是為解決不同場景而設計的。
連接,通過定義架構元素之間的接口和交互關系、集成機制,實現架構元素之間的連接。連接可以是分布式調用、進程間調用、組件之間的交互關系等。總結一下架構的組成 = 要素 + 結構 + 連接,將系統要素按照特定結構進行連接交互。
我在這重新定義架構(見仁見智):
軟件架構指軟件系統頂層結構設計。
架構是經過系統性地思考,權衡利弊之后在現有資源約束下的最合理決策,最終明確的系統骨架:包括子系統、模塊、組件,以及他們之間協作關系、約束規范、指導原則,并由它來指導系統各方面的設計和指導團隊中的每個人思想層面上的一致。
涉及四方面:
???系統性思考的合理決策:比如技術選型、解決實施方案(包括執行目標計劃)、成本評估、性價比評估等等。
???結構:明確的系統骨架(結構):明確系統有哪些構件組成。
???連接:系統協作關系:各個組成部分如何協作來實現業務請求。
???規范:約束規范和指導原則:保證系統有序,高效、穩定運行,包括規范、原則、流程等內容。
02 沒有架構設計?也許你的系統還不夠復雜
如果沒有架構設計,說明你的系統不夠復雜。隨著業務的增長,系統由單體應用漸進演化為分布式和微服務化。
系統整體的復雜性越來越高,技術團隊可能從一個團隊變成多個專業化團隊。假如沒有架構設計,系統定會是一個無序失控的狀態,帶來的問題:
問題 | 原因 |
應用服務的邊界不清晰 | 到底該怎么拆分沒有一個明確的原則,研發人員為了所謂微服務化而拆分,而不是從當前業務考慮。導致系統無序地狀態,開發效率低。我們系統出現過類似的情況:一個簡單項目拆分成8個子服務,問他為什么這么拆分,說微服務化是為了應對以后擴展方便。結果這個項目從2017年到現在都沒有再修改過,接手人寧愿新開發一個項目也不愿重構。 |
應用服務層次不清晰,系統耦合嚴重 | 導致服務依賴出現網狀依賴結構,牽一發動全身,后續修改和擴展困難。 |
系統應用服務跟蹤問題 | 由于微服務化后,系統邏輯復雜,服務出現問題后,你很難快速地定位問題和修復。這是我們踩過不少坑,我們使用 dubbo 服務化,系統一旦出現問題,一堆人手忙腳亂。 |
系統服務監控問題 | 由于研發人員基本沒有服務監控意識,都是出現問題后再想辦法如何添加服務監控接口。 |
技術體系失控問題 | 不同的開發團隊使用不同的技術棧或者組件,造成公司內部的技術架構失控。甚至研發人員為追求時髦新潮技術,拿應用項目來試驗新技術。 |
當然,我們還能列舉出更多問題。
架構設計的目的是為了解決系統復雜性帶來的問題。其本質就是對系統進行有序化地重構以致符合當前業務的發展,并可以快速擴展。
從上面架構的定義,也知道架構設計的作用涉及四方面:系統性思考的合理決策;明確的系統骨架;系統協作關系;約束規范和指導原則。
無論是何種變化,架構師通過理解業務、全局把控,權衡業務需求和技術實現。選擇合適技術,解決關鍵問題并指導研發落地實施,最終促進業務發展,提高效率。
03 此架構非彼架構?架構到底怎么分
在 EA 架構領域,有兩種常見架構方法 RUP 和 TOGAF,這兩個框架也是我們常常了解架構分類的兩個維度。
從我個人的角度覺得 TOGAF 的分類方式更加廣泛使用,因此本次分享我簡單展開介紹?TOGAF ,如果你對?RUP 感興趣,推薦閱讀1995年,Philippe Kruchten 在《IEEE Software》上發表了題為《The 4+1 View Model of Architecture》的論文。
TOGAF9 對架構的分類是這樣的:
架構類型 | 描述 |
業務架構 | 業務戰略、治理、組織和關鍵業務流程。 |
數據架構 | 組織的各類邏輯和物理數據資產以及數據管理資源的結構。 |
應用架構 | 描述被部署的單個應用系統、系統之間的交互,以及它們與組織核心業務流程之間關系的藍圖。 |
技術架構 | 對于支持業務、數據和應用服務的部署來說必需的邏輯軟、硬件能力。包括1T基礎設施、中間件、網絡、通信、部署處理和一些標準等。 |
由于不同架構方法論,定義的架構分類也不同,RUP4+1架構方法主要是以架構生命周期為視角進行描述,而 TOGAF9 按架構涉及內容維度來描述。
因此我結合兩者細分為業務架構、應用架構、數據架構、技術架構、代碼架構、部署架構。
業務架構是戰略,應用架構是戰術,技術架構是裝備。其中應用架構承上啟下,一方面承接業務架構的落地,另一方面影響技術選型。熟悉業務,形成業務架構;根據業務架構作出相應的應用架構,最后技術架構落地實施。
你也可以理解成:業務架構是生產力,應用架構是生產關系,技術架構是生產工具。業務架構決定應用架構,應用架構需要適配業務架構,并隨著業務架構不斷進化,同時應用架構依托技術架構最終落地。
04
架構師都在說的單體應用、分布式與微服務到底是什么?
整體來說,架構演進路程是這樣的:
單體應用->分布式應用服務化->微服務
下面我將做簡單介紹。
???4.1??單體應用?
企業一開始業務比較簡單,只應用某個簡單場景,應用服務支持數據增刪改查和簡單的邏輯即可,單體應用可以滿足要求。
典型的三級架構:前端(Web/手機端)+中間業務邏輯層+數據庫層。這是一種典型的 Java Spring MVC 或者 Python Django 框架的應用。針對單體應用,非功能性需求的做法:
???性能需求:使用緩存改善性能;
???并發需求:使用集群改善并發;
???讀寫分離:數據庫的讀寫分離;
???使用反向代理和 cdn 加速;
???使用分布式文件和分布式數據庫。
單體架構的應用比較容易部署、測試, 在項目的初期,單體應用可以很好地運行。然而,隨著需求的不斷增加, 越來越多的人加入開發團隊,代碼庫也在飛速地膨脹。
慢慢地,單體應用變得越來越臃腫,可維護性、靈活性逐漸降低,維護成本越來越高。總體來說,單體架構應用可能會有這些缺點:復雜性高、技術債務積累、部署頻率低、可靠性差、擴展能力受限并且可能阻礙技術創新。
???4.2??分布式?
為了解決上面提到的這些缺點,我們需要對系統按照業務功能模塊拆分,將各個模塊服務化,變成一個分布式系統。
業務模塊分別部署在不同的服務器上,各個業務模塊之間通過接口進行數據交互。該架構相對于單體架構來說,這種架構提供了負載均衡的能力,大大提高了系統負載能力,解決了網站高并發的需求。另外還有以下特點:
降低耦合度:把模塊拆分,使用接口通信,降低模塊之間的耦合度。 責任清晰:把項目拆分成若干個子項目,不同的團隊負責不同的子項目。 擴展方便:增加功能時只需要再增加一個子項目,調用其他系統的接口就可以。 部署方便:可以靈活地進行分布式部署。 提高代碼的復用性:比如 Service 層,如果不采用分布式 rest 服務方式架構就會在手機 Wap 商城,微信商城,PC,Android,iOS 每個端都要寫一個 Service 層邏輯,開發量大,難以維護一起升級,這時候就可以采用分布式 rest 服務方式,公用一個 service 層。 *缺點:系統之間的交互要使用遠程通信,接口開發增大工作量,但是利大于弊。 |
???4.3?微服務?
隨著業務模式越來越復雜,訂單、商品、庫存、價格等各個模塊都很深入,比如價格區分會員等級,訪問渠道(app 還是 PC),銷售方式(團購還是普通)等,還有大量的價格促銷。
這些規則很復雜,容易相互沖突。我們需要把分散到各個業務的價格邏輯進行統一管理,以基礎價格服務的方式透明地提供給上層應用,變成一個微內核的服務化架構,即微服務。
微服務的特點明顯:易于開發與維護、單個微服務啟動較快、局部修改容易部署、技術棧也不受限制。
然而,微服務雖然有很多吸引人的地方,但它并不是免費的午餐,使用它可能面臨這些挑戰:
運維要求較高:更多的服務意味著更多的運維投入。在單體架構中,只需要保證一個應用的正常運行。而在微服務中,需要保證幾十甚至幾百個服務的正常運行與協作,這給運維帶來了很大的挑戰。 分布式固有的復雜性:使用微服務構建的是分布式系統。對于一個分布式系統,系統容錯、網絡延遲、分布式事務等都會帶來巨大的挑戰。 接口調整成本高:微服務之間通過接口進行通信。如果修改某一個微服務的API,可能所有使用了該接口的微服務都需要做調整。 重復勞動:很多服務可能都會使用到相同的功能,而這個功能并沒有達到分解為一個微服務的程度,這個時候,可能各個服務都會開發這一功能,從而導致代碼重復。盡管可以使用共享庫來解決這個問題(例如可以將這個功能封裝成公共組件,需要該功能的微服務引用該組件),但共享庫在多語言環境下就不一定行得通了。 |
05 15條普適的架構設計原則
我們掌握前人總結的經驗,讓我們站在巨人的肩膀上高山遠矚。《架構真經》這本書簡單闡述了架構設計的一些常用的原則。下面我結合原作品,分享15個具有普適價值架構原則:
???5.1?N+1設計 :開發的系統在發生故障時,至少有一個冗余的實例?
?廣泛地應用在從數據中心設計到應用服務的部署:
???在發生故障時,系統至少要有一個冗余的實例。
???必須確保一個為自己,一個為客戶、 一個為失敗。
???5.2?回滾設計 :確保系統可以向后兼容?
???如果很久才能修復服務,那么就要在一定的時間范圍內完成回滾。
???災難性的事故,例如損壞客戶數據,往往在部署后好幾天才出現。
???系統最好按照預先的設計,通過發布或回滾解決問題。
通過版本化方式實現回滾設計,一旦發生災難級別的故障可以通過回滾到最近版本來恢復服務。
???5.3?禁用設計(功能開關、降級開關):可以關閉任何發布功能?
當設計系統,特別是與其他系統或服務通訊的高風險系統時,要確保這些系統能夠通過開關來禁用。這將為修復服務提供額外的時間,同時確保系統不因為錯誤引起詭異需求而宕機。
降級開關通過配置中心集中化管理,例如:apollo 配置中心,通過推送機制把開關推送到各個應用服務。
???5.4?監控設計:在設計階段就要考慮監控,而不是在部署完成后?
???通過監控發現系統的可用性問題。
???通過監控使系統自我診斷、自我修復成為可能。
???通過監控確定系統可預留空間的使用情況。
???通過監控掌握系統之間的交互關系,發現瓶頸 。
如果監控做得好,不僅能發現服務的死活,檢查日志文件,還能收集系統相關的數據,評估終端用戶的響應時間。如果系統和應用在設計和構建時就考慮好監控,那么即使不能自我修復,也至少可以自我診斷。
???5.5?多活數據中心設計
???數據是否全部集中在一個數據中心?
???讀寫是否分離?
???是否所有的客戶信息都共享同一個數據結構?
???服務調用是否允許延時的存在?
???5.6?采用成熟的技術?
工程師傾向于學習和實施性感時髦的新技術。因為新技術可以降低成本、減少產品上市時間、提高性能。不幸的是,新技術也往往有較高的故障率。如果把新技術應用在架構的關鍵部分,可能會對可用性產生顯著的影響。
最好爭取在多數人采用該技術的時候進入,先把新技術用在對可用性要求不高的功能上,一旦證明它可以可靠地處理日常的交易,再將此技術移植到關鍵任務領域中去。
???5.7 故障隔離?
避免單一業務占用全部資源,避免業務之間的相互影響。機房隔離避免單點故障。兩個重要原則:
???不共享原則:理想情況是負載均衡、網絡前端、應用服務器、數據庫,絕不共享任何服務、硬件和軟件。
???不跨區原則: 不同隔離區之間無通訊,所有服務調用必須發生在同一個故障隔離區。
???5.8 水平擴展?
什么是水平可擴展?平臺的水平擴展是指隨著業務的發展,當需要擴大平臺的服務能力時,不必重構軟件系統,通過增加新的設備來滿足業務增長的需要。?
X軸擴展:服務器拆分。平臺的服務能力可以在不改變服務的情況下,通過添加硬件設備來完成擴容。 Y軸擴展:數據庫拆分。平臺的服務能力通過不斷地分解和部署服務來完成擴容。 Z軸擴展:功能拆分。平臺的服務能力可以按照客戶不斷分解和部署來機器 完成容量的擴展。(比如按用戶 uid 來分表分庫等) |
???5.9?非核心則購買??
工程師往往有自己研發所有系統的沖動。如果使用云服務器,建議直接使用云服務相關產品比如日志系統,可以直接使用日志服務。
???系統研發要投入資源,系統維護更要長期投入。
???影響核心產品到市場的速度。
???如果可以形成差異化的競爭優勢,那么自己做,否則外購。
???5.10?使用商品化硬件?
在大多數情況下,便宜的是最好的。標準、低成本、可互換、易于商品化是商品化硬件的特征。
如果架構設計得好,就可以通過購買最便宜的服務器輕松地實現水平擴展,前提是所有商品化硬件的總成本要低過高端硬件的總成本。
???5.11?快速迭代?
這里有三個要點:
???小構建:小構建的成本較低,可以確保投資可以產生價值。
???小發布:發布的失敗率與變更數量相關,小發布失敗率較低。
???快試錯:可依市場反饋,快速迭代,加快TTM,優化用戶體驗。
快速迭代需要完善的運維工具,比如從 cmdb、持續集成工具、監控等等。
???5.12?異步設計?
同步系統中個別子系統出現故障會對整個系統帶來影響。這里常有2個現象:
???同步系統中性能最慢的子系統,成為整個系統性能的瓶頸。
???同步系統中擴展性最差的子系統,是整個系統擴展的瓶頸。?
???5.13?無狀態設計?
無狀態定義:是應用服務運行的實例不會在本地存儲需要持久化的數據,并且多個實例對于同一個請求響應的結果是完全一致的。比如單實例的 mysql,zookeeper 集群是有狀態,而類似單純 tomcat 服務是無狀態的。
無狀態的系統更利于擴展,更利于做負載均衡。狀態是系統的吞吐量、易用性、可用性、性能和可擴展性的大敵,要盡最大可能避免。
???5.14 前瞻性設計?
???Now?:目前正使用系統的架構、設計、能力、性能和擴展性。
???Now+1: 下一代預研系統的架構、設計、能力、性能和擴展性。
???Now+2: 下一代規劃系統的架構、設計、能力、性能和擴展性。
???5.15自動化?
設計和構建自動化的過程。如果機器可以做,就不要依賴于人。人常犯錯誤,更令人沮喪的是,他們往往會以不同的方式多次犯同樣的錯誤。
06 6個架構設計的誤區
最后,想跟各位分享幾個我親身總結的架構設計誤區,希望能夠給你一些靈感。
|
???誤區1——架構專門由架構師來做,業務開發人員無需關注
架構得再好,最終還是需要代碼來落地,并且組織越大這個落地的難度越大。不單單是系統架構,每個解決方案每個項目也由自己的架構,如分層、設計模式等。
如果每一塊磚瓦不夠堅固,那么整個系統還是會由崩塌的風險。所謂“千里之堤,潰于蟻穴”。
???誤區2——架構師確定了架構藍圖之后任務就結束了
架構不是“空中樓閣”,最終還是要落地的,但是架構師完全不去深入到第一線怎么知道“地”在哪、怎么才能落得穩穩當當?
???誤區3——不做出完美的架構設計不開工
世上沒有最好架構,只有最合適的架構,不要企圖一步到位。我們需要的不是一下子造出一輛汽車,而是從單輪車 --> 自行車 --> 摩托車,最后再到汽車。
你想象一下2年后才能造出的產品,當初市場還存在嗎?
???誤區4—— 為虛無的未來埋單而過度設計
在創業公司初期,業務場景和需求邊界很難把握,產品需要快速迭代和變現,需求頻繁更新,這個時候需要的是快速實現。不要過多考慮未來的擴展,說不定功能做完,效果不好就無用了。
如果業務模式和應用場景邊界都已經比較清晰,是應該適當的考慮未來的擴展性設計。
???誤區5——一味追隨大公司的解決方案
由于大公司巨大成功的光環效應,再加上從大公司挖來的技術高手的影響,網站在討論架構決策時,最有說服力的一句話就成了“xx就是這么搞的”。
大公司的經驗和成功模式固然重要,值得學習借鑒。但如果因此而變得盲從,就失去了堅持自我的勇氣,在架構演化的道路上遲早會迷路。
???誤區6——為了技術而技術
技術是為業務而存在的,除此毫無意義。在技術選型和架構設計中,脫離網站業務發展的實際,一味追求時髦的新技術,可能會將技術發展引入崎嶇小道,架構之路越走越難。
考慮實現成本、時間、人員等各方面都要綜合考慮。理想與現實需要折中。