自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

程序員過關斬將--論系統(tǒng)設計的高可擴展性

系統(tǒng)
說到系統(tǒng)設計的三高,每一高都是一個很龐大的話題,甚至可以用一本書甚至N本書來詳細闡述。其中高可擴展性是系統(tǒng)架構的眾多目標之一。歸根結底,系統(tǒng)的架構要為最終的業(yè)務服務,脫離業(yè)務來談架構其實比耍流氓更無恥。

[[354672]]

此文僅僅代表個人意見,并非行業(yè)標準

“MQ是萬能的高擴展方式?

“面向接口是萬能的高擴展方式?

說到系統(tǒng)設計的三高,每一高都是一個很龐大的話題,甚至可以用一本書甚至N本書來詳細闡述。其中高可擴展性是系統(tǒng)架構的眾多目標之一。歸根結底,系統(tǒng)的架構要為最終的業(yè)務服務,脫離業(yè)務來談架構其實比耍流氓更無恥。

在我們心目中最理想的軟件架構要像搭積木一樣簡單,并且快捷,而且高效。但是現實往往比996更殘酷,多數的系統(tǒng)在初期為了配合業(yè)務快速上線,擴展性這個指標并不理想。別的不談,一個系統(tǒng)要完美的做到“對修改封閉,對擴展開放”其實一點也不簡單,不知道你有沒有遇到過修改一個bug蹦出另外一個bug的痛苦經歷?

為了做到系統(tǒng)的高擴展性,其實有很多借鑒的案例,尤其是設計模式。但是今天我還是要說一說我自己的看法。無論什么樣的系統(tǒng),抽象起來其實都是模塊和模塊之間的交互,這里模塊的含義是廣義的,即可以代表函數,也可以代表進程,甚至可以代表目前流行的微服務,如下圖所示

image

圖是不是很簡單?但是要想把A和B之間的交互做到高擴展其實并不容易,這要求系統(tǒng)的設計者必須要想辦法在滿足A和B正常交互的情況下盡量解耦A和B,只有正確的解耦,才能從容的應對A和B獨立擴展的業(yè)務需求

同一進程內

在同一進程內的情況是一種最常見的存在方式,對應到我們平時的代碼,表現為函數的調用,而這里的函數調用可以是同一模塊內的函數調用,比如最典型的三層架構中,業(yè)務層調用持久化層來進行數據的操作,如下代碼:

  1. //user 業(yè)務層 
  2.     public class UserBLL 
  3.     { 
  4.         UserDAL dal = new UserDAL(); 
  5.         public int AddUser(User user
  6.         { 
  7.             //其他業(yè)務 
  8.             return dal.AddUser(user); 
  9.         } 
  10.         
  11.     } 
  12.  
  13.     //user持久化層 
  14.     public class UserDAL 
  15.     { 
  16.         public int AddUser(User user
  17.         { 
  18.             //進行數據庫操作 
  19.             return 0; 
  20.         } 
  21.     } 

我真的希望實際項目中的代碼能像以上代碼這么簡單,畢竟代碼就和項目一樣,簡單即是美。這段代碼排除業(yè)務之外,從架構來講也有很多問題,用開頭的A和B的方式來表示,A代表的是UserBLL,B代表的是UserDAL,這里最容易看出的就是強耦合,即:A嚴重依賴于B,如果B有什么風吹草動,勢必會影響A的執(zhí)行。

怎么辦呢?所以有了B的抽象層,對應到代碼上是IDAL接口層,當然這個抽象層應該是穩(wěn)定的,如果三天兩頭修改抽象層,那說明抽象的有問題。A在執(zhí)行上改為依賴IDAL,這是系統(tǒng)內設計最常見的面向接口設計模式,其實更準確的說,應該是面向抽象設計模式。由于引入了穩(wěn)定的抽象層,不再穩(wěn)定的實現層就可以根據實際的業(yè)務去修改,這里體現的是系統(tǒng)設計中依賴倒置的原則,當然為了實現依賴倒置,你可能需要使用IOC等技術來實現項目落地。

  1. //user 業(yè)務層 
  2.     public class UserBLL 
  3.     { 
  4.         IUserDAL dal = "依賴注入"
  5.         public int AddUser(User user
  6.         { 
  7.             //其他業(yè)務 
  8.             return dal.AddUser(user); 
  9.         } 
  10.         
  11.     } 
  12.  
  13.     //user的持久化層抽象 
  14.     public interface IUserDAL 
  15.     { 
  16.         int AddUser(User user); 
  17.     } 
  18.  
  19.     //user持久化層 
  20.     public class UserDAL: IUserDAL 
  21.     { 
  22.         public int AddUser(User user
  23.         { 
  24.             //進行數據庫操作 
  25.             return 0; 
  26.         } 
  27.     } 

不同進程間

不同的進程之間互相協作是目前分布式模式下主要的交互方式,例如之前的SOA,現在的微服務,都是在利用分散在不同位置的模塊來組裝系統(tǒng),這些模塊之間的通信是一個分布式系統(tǒng)必備的條件。

和進程內函數調用類似,分布式系統(tǒng)也可以抽象為A和B的關系模型,我們要解決的也是A和B能夠獨立變化的問題?,F在假設A服務依賴于B服務,B服務由于壓力大需要擴容,會有哪些影響呢?

  • B自己內部的狀態(tài)變化,如果B服務是有狀態(tài)的,擴展起來可能會設計到數據的遷移等操作,如果B是無狀態(tài)的,理論來說可以很方便的橫向擴展
  • B的擴容對A或者其他依賴于B的系統(tǒng)有什么影響,依賴方能否做到自動適配,而不必修改任何配置

和進程內函數調用不同,進程間的通信需要通訊協議的支持,最常見的RPC調用都是基于TCP協議,Restfull基于http協議,使用這些協議底層都需要指定明確的IP和端口。所以需要某種解決方案在被依賴方擴展的時候,依賴方能夠得到感知。聰明的你可能想到了“注冊中心”,不錯,這也是注冊中心最主要的職責。

解決方案2

用注冊中心的方式,理論上屬于通知依賴方的方案,在依賴方感知被依賴方有擴展變動的時候,需要作出對應的變化。與之對應的其實我們也可以把變動封裝在被依賴方,這個時候就引入了以下代理模式,最常見的就是網關模式。

分布式系統(tǒng)使用網關到底是好還是壞?

其實代理模式非常常見,比如Nginx做反向代理,數據庫的中間件。這些設施都是對依賴方透明的,依賴方不會因為被依賴方實施了擴展而受影響。

解決方案3

目前很多業(yè)務下有一種很常見的場景,依賴方和被依賴方通信并不需要知道執(zhí)行結果,最典型的場景像:新用戶注冊給用戶發(fā)歡迎郵件或者短信歡迎語。如果業(yè)務代碼中冗余了發(fā)郵件或者短信的代碼的話,一旦要添加新的歡迎方式就必須要修改業(yè)務代碼,無論你是否有抽象層,為了不影響主要的業(yè)務又最大化解耦系統(tǒng),一般都會把這種非主要業(yè)務通過消息的方式分離出來。最常見的解決方案就是MQ。這也是典型發(fā)布訂閱模式,但是這種模式如上所說,調用方并不能實時的得到業(yè)務處理結果。

利用MQ來進行系統(tǒng)的解耦,來實現系統(tǒng)的高可擴展是一種非常常見的方式,優(yōu)勢有很多,我不再闡述,但是需要注意消息的可靠性,因為消息經過了幾個環(huán)節(jié)之后,難保某個環(huán)節(jié)出現問題而丟失消息。

寫在最后

A和B之間的通信如果只是單向的話,可以理解為上下級關系,但是在微服務情況下,A和B很多時候是平行的互相調用的兄弟關系。有的架構師不贊成平行關系的微服務互相調用,這是有一定道理的,因為這很容易造成復雜的網絡調用模式,如果是符合MQ消息的形式通信,我也推薦首推利用MQ來解耦服務間的依賴。

高可擴展性系統(tǒng)的最終目標是在應對業(yè)務變化的時候,用最小的代價去實現。而如何實現系統(tǒng)的擴展性,并非只有以上所說的“面向接口編程”,利用MQ這些方式,你還知道哪些可以幫助系統(tǒng)擴展的解決方案嗎?歡迎你給我留言!!

“只要一提到解耦,有的“高手”一上來就說利用MQ,真的對嗎?如果調用方需要實時的業(yè)務處理結果呢?

本文轉載自微信公眾號「架構師修行之路」,可以通過以下二維碼關注。轉載本文請聯系架構師修行之路公眾號。

 

責任編輯:武曉燕 來源: 架構師修行之路
相關推薦

2020-08-25 07:35:07

session分布式抽象

2020-12-29 08:01:22

安全登錄系統(tǒng)

2020-09-01 08:10:47

高并發(fā)系統(tǒng)程序員

2020-12-15 08:05:02

redis單線程多線程

2021-03-03 07:29:00

開閉依賴倒置原則

2024-10-10 14:01:34

2021-09-02 09:42:11

測試軟件可擴展性開發(fā)

2023-12-20 09:26:20

高可用高吞吐高擴展性

2022-09-05 15:17:34

區(qū)塊鏈比特幣可擴展性

2020-11-03 07:43:24

MQ版本號程序員

2021-12-03 14:41:00

云存儲可擴展性存儲

2012-06-04 11:04:46

虛擬化

2016-10-13 14:38:51

OpenStack可擴展性IT人員

2021-05-17 07:28:23

Spring可擴展性項目

2021-12-09 05:36:16

云存儲可擴展性數據存儲云存儲

2013-04-09 10:16:28

OpenStackGrizzlyHyper-V

2010-03-18 11:01:34

VMware

2009-04-20 11:33:47

光網絡動態(tài)擴展

2017-01-05 19:29:10

公共云云存儲微軟

2023-05-17 15:53:21

點贊
收藏

51CTO技術棧公眾號