垂直方向架構
多層架構
分層架構通過程序包或者程序的隔離構建鬆耦合的應用。我們以最近流行的洋蔥架構模型進行分析,如圖
領域模型
包括領域實體/存儲接口/服務接口,是整個程序的核心。
- 貧血模型
如果把大量的業務邏輯委託給服務接口實現者,領域模型顯得很瘦小,就可以稱之爲貧血模型。這種模型下的領域對象僅僅表示“狀態”。“行爲”(也稱爲邏輯、過程)放在了N層結構的Logic/Service/Manager層中。優點是易於理解和實現,缺點是隨着業務發展模型會難以表達業務領域。目前不少業內軟件架構是這種模式。
貧血模型的簡單圖示:
- 充血模型
如果在領域模型中實現主要的業務邏輯,把不方便實現的業務(比如匯率結算,地理座標解析等)委託給服務接口實現者,此時領域模型顯得粗壯,就可以稱之爲充血模型。這種模型下的領域對象既表示“狀態”又有”行爲“,領域對象之間還通過聚合在一個根(聚合根),然後由根對象保證狀態的一致性(類似於數據庫表之間的約束一致性)。優點是模型易於跟進業務發展,容易通過重構表達最新的業務領域;缺點是不易掌握。
充血模型的簡單圖示:
存儲倉庫
領域模型中的對象自從被創建出來後不會一直留在內存中活動,當它不活動時會被持久化到數據庫中,然後當需要的時候就會重建該對象;重建對象就是根據數據庫中已存儲的對象的狀態重新創建對象的過程。可見持久化和重建對象是一個和數據庫打交道的過程。從更廣義的角度來理解,程序會像集合一樣從某個類似集合的地方根據某個條件獲取一個或一些對象,往集合中添加對象或移除對象。也就是說,這就需要提供一種機制,可以提供類似集合的接口來幫助程序管理對象。倉儲就是基於這樣的思想被設計出來的。
貧血模型下的存儲倉庫:實現實體對象的CRUD.
充血模型下的存儲倉庫:創建聚合根對象,實體對象的創建/更新/刪除的行爲由聚合根完成。
服務
一般有三種服務:應用服務、領域服務、基礎服務。
- 應用服務
調用領域服務,形成工作流程,提供事物上下文。應用服務可以直接爲UI提供服務或者直接作爲API暴露出去。
- 領域服務
在具體一個業務上下文中提供服務。比如訂單生成服務提供訂單的生成功能,訂單的跟蹤服務提供訂單的執行信息。
- 基礎服務
基礎服務提供的是和業務無直接關係的工具輔助服務。比如日誌,安全,通信,事件總線等等。
UI
提供應用程序界面,支持用戶輸入。高效的UI開發往往會依賴UI框架,比如MVC框架。
UI框架比較多,比如MFC,WinForm,Asp.net WebForm,Asp.net MVC,Structs等等。
綜上:洋蔥模型的各層由外到內的單向依賴,簡單直接的降低了代碼之間的耦合度。
典型框架
數據存儲框架
數據訪問輔助
這類框架往往提供了一套操作連接/命令/結果集的接口。用戶先發起連接,發生sql命令,然後得到結果集以按行(又叫記錄)方式進行遍歷。不同的數據庫需要相應的數據庫驅動和實現,但對於用戶來說操作數據的方式都是一樣的。
優點:
1)編寫原始sql,執行效率高。
2)握有連接對象,可以自定義事物的發起,提交或者回滾。
3)可以針對不同數據存儲方式定義數據訪問庫。
4)一般比較輕量,依賴少。
缺點:
1)編寫sql容易出錯,隨着數據庫的演變,sql的潛在錯誤必須依賴充分的單元測試才能消除。
2)數據庫的演變,sql重構難度會逐漸增大。
ADO.Net框架的特點:接口清晰,支持離線遍歷數據集,支持數據庫和非數據庫數據源
對象——關係映射
對象-關係映射(Object-Relational Mapping,簡稱ORM),以面向對象的開發方法實現數據的增刪改查。
優點:
1)提高開發效率,降低開發成本
2)使開發更加對象化
3)可移植
4)可以很方便地引入數據緩存之類的附加功能
缺點:
1)自動化進行關係數據庫的映射需要消耗系統性能。其實這裏的性能消耗還不大,一般來說都可以忽略之(除非在性能特別關鍵應用)。
2)在處理多表聯查、where條件複雜之類的查詢時,ORM的語法會變得複雜。
典型框架:
框架 |
特點 |
開發語言 |
半自動;輕量級;自己寫sql語句,可操作性強,小巧 |
C# |
|
全自動;較重量級;支持寫linq和原生sql,功能強大 |
C# |
MVC框架
- Model
負責提供界面綁定的數據,以及業務邏輯處理。
- View
負責提供用戶和應用之間的交互界面。不同類型的應用交互界面不同,可以是桌面程序窗口和web頁面。
- Controller
負責收集用戶輸入事件,並分配事件給對該事件感興趣的模型處理。對MVC的理解難點在於控制器的解讀,在下面我們會用經典MVC模式和後端MVC模式分析。
經典MVC模式
這種模式大量用在複雜交互界面的桌面應用程序,比如MFC框架;以及web富應用框架中,比如AngularJS 1(儘管有人稱之爲爲MVVM框架)。
圖示:
控制器把輸入事件通知給對該事件感興趣的模型,模型更新自己的狀態並引起視圖更新,然後將更新事件通知控制器,此時如果有對該更新事件感興趣的模型會進一步進行處理。事實上控制器和模型之間構成了訂閱/發佈關係。
MVVM框架:把Controller變成了ViewModel,它與View進行雙向綁定:View的變動,自動反映在 ViewModel,反之亦然。
MVVM框架圖示:
後端MVC模式
自web應用普及開來,涌現了不少後端MVC模式,比如JAVA的Structs,.NET的Asp.net MVC等。由於頁面在瀏覽器中顯示,用戶輸入通過http到達後端。
與經典MVC模式不同,控制器直接獲得輸入事件(http請求),調用對應的模型,模型處理完後傳遞視圖對象(VO)給控制器,控制器找到合適的視圖並傳遞VO給視圖,視圖產生html/json/文件流等資源,應用程序根據資源類型Response結果。通常後端MVC的控制負責的處理比較簡單;而複雜的用戶輸入可以用前端MVC框架實現(類似經典MVC模式)。
典型框架
框架 |
特點 |
開發語言 |
前後(端) |
支持WebForm和Razor |
C# |
後 |
|
輕量,支持WebForm和Razor,路由更靈活 |
C# |
後 |
|
功能完整,支持雙向綁定,開發效率高,運行效率一般,v2版本推翻v1,性能上提高,開發更組件化 |
js |
前 |
|
思路新穎,運用Virtual Dom技術,性能高;但目標是UI組件,需配合其他庫搭建完整MVC框架 |
js |
前 |
|
非常小巧,核心庫專注視圖層。需要搭建其他組件實現完整MVC框架 |
js |
前 |
MVC模式總結
模型負責提供視圖數據和業務邏輯處理,視圖負責提供用戶交互界面,控制器將輸入事件分配到對該事件感興趣的模型。控制器居於中心位置,類似於功能膠水,但功能僅限於膠水是它不錯的定位;避免寫入過多業務邏輯代碼使控制器變得複雜,難以維護。
IOC框架
概念
用現實生活中例子引入:由於汽車依賴輪胎,如果按照正向依賴,則汽車廠商需要根據輪胎供應商能提供的輪胎來定義自己的接口(螺絲,大小等)。但如果依賴倒置一下(讓輪胎廠商依賴汽車廠商),則汽車廠商只需要定義自己的接口(螺絲,大小等)由輪胎廠商去按照這個規格規範生產,就成爲現在汽車行業的例子。這種依賴倒置是一個思想概念,需要一個容器來實現,這就是IOC框架。
圖示:
- 依賴倒置(Dependency Inversion Principle, 英文縮寫爲DIP)
從依賴具體類變換爲依賴抽象就叫依賴倒置,這是一種設計原則。
- 控制反轉(Inversion of Control,英文縮寫爲IoC)
依賴倒置的一種實現方式,通常用於構建框架,比如WinForm,WebForm程序中你可以自定義具體的窗口類,然後在窗口初始化和虛函數裏面寫代碼,框架會按照自己的一套流程運行:啓動具體窗口,調用初始化方法,在不同的運行節點調用對應的虛函數。運行控制權始終在框架手中而不是我們寫的代碼。
- 依賴注入(Dependency Injection,英文縮寫爲DI)
依賴注入也是依賴倒置的一種具體實現,是類庫設計的一種常用模式。類庫基於依賴模式設計:調用者依賴於接口,而不是具體的實現,調用者在運行時被注入所依賴接口的具體實現。注入方法不在此處贅述。
- IOC框架
IOC框架包括了控制反轉和依賴注入功能。以下通過QA的方式來讀懂IOC框架:
Q: IOC的控制是對什麼的控制?
A: 是對應用程序中對象的創建和生命週期的控制。
Q: 正向控制是什麼樣子?
A: 由應用程序new對象,並在合適的時候釋放對象。
Q: 反轉控制是什麼樣子?
A: 對象的創建和生命週期管理由IOC框架控制,而不是應用程序控制,這種情形與正向控制相反就叫做反轉控制。
Q: 控制反轉帶來了什麼好處?
A: 控制反轉不僅減輕了應用程序的代碼複雜性,更給IOC框架的擴展性帶來好處,比如IOC框架可以實現對象單例模式,多例模式,引入事物管理,日誌管理,安全管理等等功能,比如Spring產品家族。
Q: 依賴是什麼?
A: 依賴包括:臨時使用,關聯,聚合,組合,依賴關係從左到右增強。可以參考UML相關概念描述。
Q: 注入的目的是什麼?
A: 使得對象可以依賴抽象,而不是具體實現類。主要好處是讓應用程對象之間鬆耦合。
MVC模式的價值在於更好的處理洋蔥架構的UI層。
典型注入框架
框架 |
特點 |
開發語言 |
包含於微軟企業庫中,性能穩定 |
C# |
|
輕量,性能很高 |
C# |
水平方向架構
多層架構適合整體式程序,即一個程序實現了系統全部功能。隨着企業規模越來越大,會面對不斷的新需求和需求改動,在一個程序中進行擴展變得越來越難以進行。同時面對大併發的業務請求,程序在一個進程或者多個進程中運行都難以克服一個低效運行的功能代碼造成的性能瓶頸。
人們找到了解決辦法:將程序功能分割成服務程序,各服務程序在水平方向上並行開發和部署,由API連接各服務,這種方式使降低服務之間的耦合,部署更加靈活,性能調優可以針對獨立的服務。
SOA架構
面向服務的體系結構(英語:service-oriented architecture)是構造分佈式計算的應用程序的一種方法。它將應用程序功能作爲服務提供給最終用戶或者其他服務使用。
它採用開放標準、與軟件資源進行交互並採用表示的標準方式。
圖示:
服務的基本要素
- Policy(策略)
服務提供者有時候會要求服務消費者與某種策略通信。比如要求消費者提供安全標識,才能獲取某項服務。
- Endpoint(終結點)
終結點是一個描述提供或者接受服務的方式,包括網絡協議,域名或者IP,端口信息。
- Contracts(合約)
服務合約是服務提供者(通常是遠程的)和使用者(客戶)之間使用合約語言(XML、JSON、Java Object等)約定數據輸入和數據輸出的一份協議。
- Messages(消息)
服務提供的消息,應滿足服務的合約。
服務治理
服務治理SOA最大的話題,涵蓋了以下內容:
- 服務定義(服務的範圍、接口和邊界)
- 服務部署生命週期(各個生命週期階段)
- 服務版本治理(包括兼容性)
- 服務遷移(啓用和退役)
- 服務註冊中心(依賴關係)
- 服務消息模型(規範數據模型)
- 服務監視(進行問題確定)
- 服務所有權(企業組織)
- 服務測試(重複測試)
- 服務安全(包括可接受的保護範圍)
爲了解決以上問題,最爲流行的做法在SOA架構中增加ESB(Enterprise Service Bus,即企業服務總線)集成。
微服務架構
微服務是SOA的進化版本,把服務做到微型化。
服務的基本要素
微服務架構下通過REST API提供提服務,所以不強調策略和合約,只要服務提供方暴露終結點和提供消息就足夠了。
服務治理
SOA會遇到的治理問題,在微服務中一樣會暴露出來。由於微服務系統中服務數量更多,生產環境中出現的各種問題更加突出。一部分人覺得微服務架構應該是去中心化,不需要ESB的中介作用,事實上爲微服務的網關可以具備ESB的一些功能,比如安全檢查/事物管理/複雜的工作流程等功能。
微服務架構設計模式
六種常見的微服務設計架構模式
1、聚合器微服務設計模式
這是一種最常見也最簡單的設計模式
聚合器調用多個服務實現應用程序所需的功能。它可以是一個簡單的Web頁面,將檢索到的數據進行處理展示。它也可以是一個更高層次的組合微服務,對檢索到的數據增加業務邏輯後進一步發佈成一個新的微服務,這符合DRY原則。另外,每個服務都有自己的緩存和數據庫。如果聚合器是一個組合服務,那麼它也有自己的緩存和數據庫。聚合器可以沿X軸和Z軸獨立擴展。
2、代理微服務設計模式
這是聚合模式的一個變種,如下圖所示:
在這種情況下,客戶端並不聚合數據,但會根據業務需求的差別調用不同的微服務。代理可以僅僅委派請求,也可以進行數據轉換工作。
3、鏈式微服務設計模式
這種模式在接收到請求後會產生一個經過合併的響應,如下圖所示:
在這種情況下,服務A接收到請求後會與服務B進行通信,類似地,服務B會同服務C進行通信。所有服務都使用同步消息傳遞。在整個鏈式調用完成之前,客戶端會一直阻塞。因此,服務調用鏈不宜過長,以免客戶端長時間等待。
4、分支微服務設計模式
這種模式是聚合器模式的擴展,允許同時調用兩個微服務鏈,如下圖所示:
5、數據共享微服務設計模式
自治是微服務的設計原則之一,就是說微服務是全棧式服務。但在重構現有的“單體應用(monolithic application)”時,SQL數據庫反規範化可能會導致數據重複和不一致。
因此,在單體應用到微服務架構的過渡階段,可以使用這種設計模式,如下圖所示:
在這種情況下,部分微服務可能會共享緩存和數據庫存儲。不過,這只有在兩個服務之間存在強耦合關係時纔可以。對於基於微服務的新建應用程序而言,這是一種反模式。
6、異步消息傳遞微服務設計模式
雖然REST設計模式非常流行,但它是同步的,會造成阻塞。因此部分基於微服務的架構可能會選擇使用消息隊列代替REST請求/響應,如下圖所示:
微服務優缺點
- 優點
關鍵點:複雜度可控,獨立按需擴展,技術選型靈活,容錯,可用性高
1)它解決了複雜性的問題。它會將一種怪異的整體應用程序分解成一組服務。雖然功能總量 不變,但應用程序已分解爲可管理的塊或服務。每個服務都以RPC或消息驅動的API的形式定義了一個明確的邊界;Microservice架構模式實現了一個模塊化水平。
2)這種架構使每個服務都能夠由專注於該服務的團隊獨立開發。開發人員可以自由選擇任何有用的技術,只要該服務符合API合同。
3)Microservice架構模式使每個微服務都能獨立部署。開發人員不需要協調部署本地服務的變更。這些變化可以在測試後儘快部署。例如,UI團隊可以執行A | B測試,並快速迭代UI更改。Microservice架構模式使連續部署成爲可能。
4)Microservice架構模式使每個服務都可以獨立調整。您可以僅部署滿足其容量和可用性限制的每個服務的實例數。此外,您可以使用最符合服務資源要求的硬件。
- 缺點
關鍵點(挑戰):多服務運維難度,系統部署依賴,服務間通信成本,數據一致性,系統集成測試,重複工作,性能監控等
1)一個缺點是名稱本身。術語microservice過度強調服務規模。但重要的是要記住,這是一種手段,而不是主要目標。微服務的目標是充分分解應用程序,以便於敏捷應用程序開發和部署。
2)微服務器的另一個主要缺點是分佈式系統而產生的複雜性。開發人員需要選擇和實現基於消息傳遞或RPC的進程間通信機制。此外,他們還必須編寫代碼來處理部分故障,因爲請求的目的地可能很慢或不可用。
3)微服務器的另一個挑戰是分區數據庫架構。更新多個業務實體的業務交易是相當普遍的。但是,在基於微服務器的應用程序中,您需要更新不同服務所擁有的多個數據庫。使用分佈式事務通常不是一個選擇,而不僅僅是因爲CAP定理。許多今天高度可擴展的NoSQL數據庫都不支持它們。你最終不得不使用最終的一致性方法,這對開發人員來說更具挑戰性。
4)測試微服務應用程序也更復雜。服務類似的測試類將需要啓動該服務及其所依賴的任何服務(或至少爲這些服務配置存根)。再次,重要的是不要低估這樣做的複雜性。
5)Microservice架構模式的另一個主要挑戰是實現跨越多個服務的更改。例如,我們假設您正在實施一個需要更改服務A,B和C的故事,其中A取決於B和B取決於C.在單片應用程序中,您可以簡單地更改相應的模塊,整合更改,並一次性部署。相比之下,在Microservice架構模式中,您需要仔細規劃和協調對每個服務的更改。例如,您需要更新服務C,然後更新服務B,然後再維修A.幸運的是,大多數更改通常僅影響一個服務,而需要協調的多服務變更相對較少。
6)部署基於微服務的應用程序也更復雜。單一應用程序簡單地部署在傳統負載平衡器後面的一組相同的服務器上。每個應用程序實例都配置有基礎架構服務(如數據庫和消息代理)的位置(主機和端口)。相比之下,微服務應用通常由大量服務組成。例如,每個服務將有多個運行時實例。更多的移動部件需要進行配置,部署,擴展和監控。此外,您還需要實現服務發現機制,使服務能夠發現需要與之通信的任何其他服務的位置(主機和端口)。傳統的基於故障單和手動操作的方法無法擴展到這種複雜程度。因此,成功部署微服務應用程序需要開發人員更好地控制部署方法,並實現高水平的自動化。
整體式 vs SOA架構 vs 微服務架構
框架 |
前期開發效率 |
迭代開發效率 |
擴展能力 |
維護性 |
整體式 |
高 |
中,通常越來越低 |
低 |
高 |
SOA架構 |
中 |
中,趨勢比較平穩 |
中 |
中 |
微服務架構 |
低 |
高,趨勢比較平穩 |
高 |
低 |
如果是小團隊,中小項目用整體式開發更好;如果有大量或者難以重構的遺留代碼建議採用SOA架構;比如是全新的項目且預計將來會快速迭代成大項目則建議用微服務架構。
SOA典型框架
框架 |
特點 |
是否開源 |
微軟出品,目前僅在windows下運行。它支持HTTP、TCP、命名管道之間的單向和雙向消息通信,此外,在第三方擴展的幫助下,還支持任何基於消息的傳輸格式。 |
客戶端開源 |
微服務典型框架
|
|
開發語言 |
C# |
開發方 |
個人 |
維護狀態 |
一般 |
互聯網應用案例 |
暫無 |
基於協議 |
IPC |
可用的語言 |
C# |
分佈式事物 |
否 |
無狀態部署 |
是 |
服務器治理 |
提供高性能RPC遠程服務調用,採用Zookeeper、Consul作爲surging服務的註冊中心,集成了哈希,隨機,輪詢作爲負載均衡的算法,RPC集成採用的是netty框架,採用異步傳輸 |
分佈式配置 |
有 |
單元測試 |
未知 |
文章參考: