業務單系統架構設計心得(一)

sjkzy發表於2024-07-13

作為一個業務開發工程師,工作中最多的是需求開發,把需求從ppt到落地實現。隨著工作的深入,工作面也變得更廣和更深,需要面對更多的系統,更加複雜的場景。這時完成功能實現是基本要求了,想要開發能力上一個臺階,需要做好架構設計。常見的架構有:洋蔥架構、六邊形架構、整潔架構、SOA架構、CQRS架構等等。



這些架構都有一個共同點,分層。針對業務開發系統,本文總結如下業務架構,總共分為5部分:api層、流程層、服務層、資料訪問層、指令輸出層。

1.api層功能:隔離本系統與外部其他系統的互動,互動方式有rpc介面,http,mq, 定時任務等方式。 api層接收和處理入口引數以及憑藉和轉換引數,對映為內部服務,並處理內部服務出參。api層不只是做轉換,還需要理解內部服務的模型定義和領域能力,對引數建立合理的模型。

api層在設計上需要儘量滿足以下四個原則:

  1. api層儘可能薄。api層不要業務邏輯,業務邏輯下沉到流程層和服務層裡面。
  2. 滿足彈性設計,減少後續對api定義的改動。api層是跟外部互動,介面定義上儘量減少變動。彈性設計方法有:
  • 對入參和出參使用一個大物件包裝,後續變更引數時,變動收縮在物件內部;
  • 使用Map來傳遞一些可變引數;
  • 透過List實現引數規模的彈性,不斷豐富Condition模型來支援更多的引數結構和含義,比如範圍搜尋、模糊搜尋、並聯或者互斥條件含義。
  1. 引數歸一化。所有外部的請求,業務上一般需要記錄上游方的呼叫資訊,方便後面追溯請求和做業務監控。因而,需要抽離出公共模型,專門記錄呼叫方相關資訊。所有返回結果,根據是否成功有可能性:成功,失敗。 在定義成功和失敗上,為了便於上游,需要統一成功和失敗的code,在設計返回結果時需要抽離出一個標準返回模型,統一定義成功和失敗的code。比如http,只有200才表示成功,其他錯誤碼都是不同失敗原因。
  2. 上游引數對映:盡力隔離上游系統的領域內容,防止上游定義變更,帶來的大批次修改災難。

當然,api層可以做一些非業務功能,比如使用者鑑權,介面限流。

2.流程層(biz層)負責流程編排。將服務層的邏輯串聯起來完成業務邏輯。流程層主要負責組織串聯服務,可以將組織串聯功能沉澱出基礎元件功能便於複用。 流程層可以留有簡單的業務邏輯,如果本身不復雜,業務邏輯可以直接放到流程層,不必下沉到服務層再被流程層呼叫,業務架構設計中可根據情況具體分析。

3.服務層(service)系統核心模型和能力彈性的承載層,是系統功能和擴充套件性張力來源。服務層內部要進行劃分成不同的功能區,劃分方法可參考DDD,原則上各個功能區是獨立的,不應存在跨功能區呼叫的情況。

4.資料訪問層對接資料儲存,對外提供統一的介面,遮蔽儲存實現,資料儲存有mySQL, Redis, ES等。

5.輸出指令層輸出指令資料,方式有RPC, MQ, 以及http等服務。在層級上跟資料訪問層處於同一層級。輸出指令層也是跟外部服務進行互動,如有必要進行引數對映,防止下游定義變更,帶來的大批次修改災難。

業務複用

隨著系統壯大,越來越多新的功能加入,如果新功能跟現有功能在流程上具備相似之處,從原則上應該複用現有邏輯。複用現有邏輯,一方面能夠減少開發量,只需要專注差異點的開發,能夠快速交付上線;另一方面,從長遠來看,便於維護,無需多次改動。

不同業務具備公共業務點和差異業務點,業務複用可以在兩個地方實現:流程層重新編排和服務層子服務開啟差異點擴充套件。

流程層重新編排是指各個業務線在流程層各自寫一套服務編排邏輯,被編排的子服務可以分為公共子服務和差異子服務, 公共業務點放到公共子服務中,差異業務點放到差異子服務。

![流程重新編排示意圖]

服務層子服務開啟差異點擴充套件是指流程編排是相同的,在子服務中根據不同的業務線實現差異點,為了在子服務中實現差異點��需要在流程上下文中帶上業務標識。

流程層重新編排適合差異點比較大的情況下,差異子服務並非一個服務的不同實現,這種情況下將差異點直接編排成子服務更合適。服務層子服務開啟差異點適合差異比較小的場景,對於某個功能點各個服務都有自己不同的實現,這種有個好處是便於定義標準擴充套件介面,做成SPI還能夠支援動態擴充套件。實際業務線採用哪種方式要根據具體業務來定,或者兩種都採用。

擴充套件點

一個系統能夠成為優秀系統,擴充套件能力是一個必備的能力。良好的擴充套件能力不僅能夠幫助系統提高擴充套件,增強適應性,還能夠簡化系統結構,程式碼更加優雅。java中提供了多種機制對程式功能進行擴充套件,如繼承,組合,多型,介面,內部類等,框架類比如Netty, Spring同樣提供了大量自定義擴充套件點。同理,在業務系統架構設計中,剝離出變動部分,並設計為擴充套件點的形式,方便後續迭代。

鏈式擴充套件

用更形象的表述,就如資料結構中的連結串列一樣,連結串列中的節點為擴充套件節點,連結串列將多個擴充套件節點串聯起來執行。鏈式又可以分為單鏈和雙鏈。單鏈中每個節點只有一個處理器,雙鏈每個節點分為前置和後置處理器,雙鏈在執行上,節點前置處理器先正序執行,執行完後,後置處理器再逆序執行。

![單鏈擴充套件點執行圖]

![雙鏈擴充套件點執行圖]

鏈式擴充套件由擴充套件節點(擴充套件點的具體實現), 擴充套件節點鏈組成。鏈式擴充套件的擴充套件節點實現具備同等地位,圖中ExtensionOne, ExtensionTwo, ExtensionThree都是對同一擴充套件點的不同實現。註冊Extension時,將擴充套件節點編排成鏈,如果擴充套件節點無前後依賴關係,那麼節點執行順序可以任意編排。當然,有些擴充套件點是有前後的依賴關係,這種情況下就必須指定節點執行順序。在Spring中,註冊Extension變得更加簡單。直接自動從Spring中上下文中找到所有擴充套件點的實現節點,在修改節點時,無需改動註冊邏輯。

鏈式擴充套件應用廣泛,在SpringMVC中,實現攔截器,提供日誌列印,許可權校驗等工作。在訂單業務系統中,也有很多應用。比如訂單拆單流程,業務上有很多拆單規則比如大小件拆開,按照發貨倉庫拆開等等,一個訂單經過拆單規則後,將拆分成多個子單。拆單規則通常是動態變化的,這裡就非常適合採用鏈式擴充套件點。

![SpringMvc攔截器示意圖]

星型擴充套件

星型擴充套件組成上有一個分發器和多個擴充套件節點。分發器根據分發條件分發到響應的擴充套件點進行處理。

![星型擴充套件組成]

星型擴充套件邏輯簡化如下:

ini

複製程式碼if (命中業務A) {
	執行ExtensionOne;
} else if (命中業務B) {
	執行ExtensionTwo;
} else {
	執行ExtensionThree;
}

星型擴充套件的應用也很多,上一節中的業務複用,在服務層子服務開啟業務複用,需要開啟星型擴充套件來處理不同業務的差異點。 SPI雖然沒有明顯分發器,但也屬於星型擴充套件的方式。

作者:扎Zn了老Fe
連結:https://juejin.cn/post/7323883238895190035
來源:稀土掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

  1. 如果有排版格式問題,請移步 《業務單系統架構設計心得(一)》,選擇寬屏模式效果更佳。

相關文章