1. 程式人生 > >移動端工程架構與後端工程架構的思想摩擦之旅(2)

移動端工程架構與後端工程架構的思想摩擦之旅(2)

此文已由作者黎星授權網易雲社群釋出

歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗

 

 

投放工程架構調整

 

有了前面的“理論基礎”,以及躍躍欲試的心動,我們來對投放工程的架構做一次調整和優化,原則是不改變原有的業務邏輯,目的是使投放工程的業務邊界和業務功能更為清晰。

 

舊工程架構

 

資源投放系統一共分為4個工程,分別是

  • 後端前臺工程:kaola-resource-app

  • 後端離線工程:kaola-resource-offline

  • 後端後臺Web工程:kaola-resource-web

  • 前端後臺fed工程:kaola-resource-fed

其中,kaola-resource-app和kaola-resource-offline提供純dubbo服務。app提供前臺服務,負責給其他業務線上獲取投放的素材資訊;offline提供離線服務,負責給其他業務的後臺系統獲取投放相關的資料。kaola-resource-web和kaola-resource-fed分別是投放系統的Web後端和前端工程,資源的分配、稽核、投放都在該系統完成。kaola-resource-fed屬於前端工程,不在本文討論範圍內,下面介紹三個後端工程的架構體系。

 

工程依賴關係

 

點選檢視原圖

工程依賴關係如圖所示,主要分為幾類,分別是工具模組、介面模組、業務模組以及啟動模組,箭頭表示依賴關係。

  • 工具模組

kaola-common-cache:主要包含Solo快取中介軟體的封裝,JVM快取相關的不在該模組裡。
kaola-common-util:工具類,包括常量、異常資訊及util類。
kaola-resource-search->kaola-resource-generic:ndir索引服務工程。
kaola-resource-schema(圖中未列出):存放投放自帶部分模板xml的地方,暫無其他工程引用。

  • 介面模組

kaola-resource-api:提供線上和離線服務的dubbo介面。
kaola-resource-generic:通過mybatis與資料庫打交道,提供資料的工程,相當於DAO層。
kaola-resource-facade->kaola-resource-generic:提供Web層的facade介面,相當於Service層。

  • 業務實現

kaola-resource-cache->kaola-resource-api、kaola-resource-generic、kaola-common-cache:提供業務報警、disconf配置、JVM快取、NCR快取、熔斷、業務監控、執行緒池管理等功能,且提供resource-api部分facade介面的實現、Service介面定義與實現,是resource-app工程的業務實現工程。
kaola-resource-provider->kaola-resource-facade、kaola-resource-api、kaola-service-util、kaola-resource-search、kaola-resource-generic:提供web工程facade介面的實現、Service介面定義與實現。
kaola-resource-service->kaola-resource-generic、kaola-resource-api:提供offline工程facade介面的實現、Service介面定義與實現。
kaola-service-util->kaola-resource-facade、kaola-common-util、kaola-resource-api:主要包含外部模板XML校驗業務的工程。

  • 啟動模組

kaola-resource-app->kaola-resource-cache、kaola-common-cache、kaola-resource-api、kaola-resource-generic:app工程啟動入口,SpringBoot配置。
kaola-resource-offline->kaola-resource-service、kaola-resource-generic、kaola-resource-api:offline工程啟動入口,SpringBoot配置。
kaola-resource-fed:前端後臺工程
kaola-resource-web->kaola-resource-facade、kaola-resource-provider、kaola-resource-facade、kaola-resource-api、kaola-service-util、kaola-resource-search、kaola-resource-generic、kaola-common-util:web工程啟動入口,提供http服務。

 

現有工程問題

  • 工程模組命名混亂

剛接觸投放工程的時候完全不知道從何入手,只能根據啟動工程的依賴關係找到對應的業務模組。總工程裡有4個小工程,通常找一個模組的業務實現不知道去哪個模組去找。例如,從命名上來看,並不知道kaola-resource-facade是web工程的業務介面,kaola-resource-provider是web工程的業務實現,kaola-resource-service是offline工程的業務實現,對新人來說命名不夠友好。

  • 模組職責不清晰

由上面梳理的模組功能可以知道,kaola-resource-cache工程不僅承擔了快取管理、業務報警、熔斷等基礎業務,也是app工程的業務實現;kaola-resource-service既提供了業務介面,又提供了業務實現;kaola-common-util沒有發揮它作為工具類應該提供的職責和義務。總體而言,模組的職責可以通過一定的修改變得更為清晰。

  • 工具類、常量類管理混亂

目前幾乎每個工程下面都有一個util包,且工程包含多個BusinessException/ParameterException類,帶來的問題是使用時不知道用哪個類。工具類與常量類應統一為一個工具類模組,統一管理。

  • 版本依賴管理

每個工程的依賴目前都是獨立管理的,存在不同工程依賴中介軟體版本不一致的情況。主工程的pom管理機制可以優化一下,比如disconf是每個工程都要使用的,可以放在父工程使用dependencyManagement統一管理。

  • 業務程式碼分支多

當前工程存在很多業務分支,遇到業務分支時大部分是通過if/else判斷的,修改一個業務點需要修改很多地方,通常很容易遺漏,造成隱藏的bug。

 

新工程架構

 

考慮到現有工程架構的特點,在新工程的設計上採用平滑過渡的方式,後端主體還是分為web/offline/app三個小工程,這三個小工程分別採用傳統的MVC架構。前端工程由於與後端工程關係不大,後續可以遷移到新工程裡。

 

工程依賴關係調整

針對舊工程中存在的不合理的點,以及工程中存在的問題,我們對工程及工程的依賴關係進行了如下調整。

 

點選檢視原圖

紅色背景為刪除或整合的模組,包括kaola-service-util、kaola-common-util、kaola-common-cache。 黃色背景為重新命名的模組,目的是使模組功能定位更清晰,包括

  • kaola-resource-provider->kaola-resource-web-provider,表示web工程的業務實現

  • kaola-resource-facade->kaola-resource-web-facade,表示web工程的業務介面

  • kaola-resource-generic->kaola-resource-dao,表示物件關係對映,即DAO層

  • kaola-resource-service->kaola-resource-offline-provider,表示offline工程的業務實現

綠色背景為新增模組,包括kaola-resource-util、kaola-resource-offline-facade、kaola-resource-app-provider、kaola-resource-app-facade,模組的定義也比較明確。 紅色的線為可以移除的依賴關係,黃色的線表示修改為runtime依賴,綠色的線表示新增依賴。

經過上述調整後,一張更為清晰的投放工程架構圖便展現出來了。

 

點選檢視原圖

 

工程架構基本思想

新的工程架構,模組間的職責與依賴關係更為清晰。

從模組的職責來說,淺藍色表示底層提供的工具類(包括各種util、快取、索引服務等);綠色表示資料物件關係對映服務層;黃色表示對第三方暴露的api;粉紅色表示對內提供的業務介面;土黃色表示業務介面的真正實現;深藍色則是工程的啟動入口,包含各種配置檔案。

從模組的依賴關係來說,啟動工程在編譯期僅依賴業務介面,執行時才會依賴業務實現以及與業務實現相關的底層服務,這一操作通過maven的scope標籤完成,編譯期編譯使用的標籤為<scope>compile</scope>,執行時編譯使用的標籤為<scope>runtime</scope>。索引、快取、工具類作為基礎服務以獨立的模組存在,需要與資料庫打交道的模組則直接依賴kaola-resource-dao即可。

對於當前的架構還不是最完美的,存在兩個問題。

  1. kaola-resource-cache提供了kaola-resource-api的實現,應將這一部分的業務邏輯移至kaola-resource-app-provider中。

  2. 業務介面依賴了kaola-resource-dao,這一部分因為介面使用了dao層的Entity,需要重新規劃建模,去除對dao層的依賴。

該架構的設計可以做到業務層僅和介面打交道,在業務層實現業務邏輯時,不關心底層服務的實現。業務層也沒有辦法直接和dao層打交道,避免資料被業務層無故修改。

 

工程模組劃分

  • 基礎模組/服務

kaola-resource-fed:前端工程單獨拆出,不與後端工程公用同一個git倉庫
kaola-resource-util:工具類、異常類、常量,可以被所有子工程引用
kaola-resource-cache:快取相關的模組,需要使用快取的工程引用此module
kaola-resource-index:索引工程服務
kaola-resource-dao:資料庫dao層
kaola-resource-api:暴露對第三方提供的所有服務api,包括online和offline介面
kaola-resource-facade-base:存放所有facade工程的基礎介面和異常類,上述流程圖沒有展示出來,但確實是有必要的基礎模組。

  • web工程

kaola-resource-web-facade:web工程服務暴露,僅提供facade介面和資料實體類
kaola-resource-web-provider:web工程服務實現,根據需要自定義service層元件
kaola-resource-web:web工程啟動類,compile依賴facade,runtime依賴provider

  • offline工程

kaola-resource-offline-facade:offline工程內部服務,僅提供介面和資料實體類
kaola-resource-offline-provider:offline工程服務實現,及部分kaola-resource-api實現,提供dubbo provider
kaola-resource-offline:offline工程啟動類,compile依賴facade,runtime依賴provider

  • app工程

kaola-resource-app-facade:app工程內部服務,僅提供介面和資料實體類
kaola-resource-app-provider:app工程服務實現,及部分kaola-resource-api實現,提供dubbo provider
kaola-resource-app-starter:app工程啟動類,compile依賴facade,runtime依賴provider

 

現有工程改造方案

 

工程模組改造

在上述改造原則基礎上,投放工程的模組改造計劃可以清晰地列出來。針對基礎模組來說,需要進行如下改造:

  • 新增kaola-resource-facade-base工程,存放facade的異常類

  • kaola-common-cache重新命名為kaola-resource-cache

  • kaola-common-util重新命名為kaola-resource-util

  • kaola-resource-generic重新命名為kaola-resource-dao

  • 新增kaola-resource-facade-base工程,存放facade的異常類

剩餘的三個工程,以resource-web工程為例,需要進行如下改造:

  • 將kaola-resource-facade重新命名為kaola-resource-web-facade,存放對web工程提供的服務介面,將BusinessException和ParameterException移除放到facade-base工程中

  • kaola-resource-provider重新命名為kaola-resource-web-provider,將模組中的util遷移至resource-util工程

  • kaola-service-util中非業務相關的所有util全部移動到kaola-resource-util這個module中,剩餘業務相關的,移動到kaola-resource-web-provider工程

  • kaola-resource-web,將web對provider的依賴由compile改為runtime

offline和app工程採用類似的方案,不再贅述。

 

maven依賴改造

maven依賴改造的目的,一是減少由於版本依賴不一致帶來的新坑,方便第三方中介軟體的統一管理;二是對工程許可權有所約束,不至於程式碼亂放,難以維護。

  • 共有的jar包依賴管理 在父pom增加dependencyManagement標籤,把常用的Spring、log、guava、junit、jsonserializer、disconf和網易自研的中介軟體等jar包統一進行版本管理。子工程需要相關元件時,僅需引入依賴,無需指定版本。

  • 模組依賴許可權管理 由改造後的工程架構可知,啟動工程是沒有辦法接觸到業務實現的,這需要依靠runtime時再依賴業務實現模組來實現。因此,對於每個需要依賴*-provider的工程,都需要通過runtime來依賴。

  • api版本釋出管理 需要對外發布的包,依賴儘量使用provided引入。在父pom增加本地api釋出的版本,子工程如需依賴api或實現api的業務,需要引用父pom的api版本,api版本的升級,需要同時升級父pom和api模組工程兩個地方 resource-util工程與api工程管理一致。

 

TODO

 

  • kaola-resource-api遷移所有page相關的api介面

  • kaola-resource-fed遷移使用新的git工程

  • kaola-resource-cache邏輯遷移

  • kaola-resource-dao業務介面的依賴去除

 

架構調整總結

 

架構永遠是聊不完的話題,特別是涉獵了知識面較廣的後端以後,越發感覺需要學習的東西越來越多。本文分別從移動端和後端的架構思想談起,從中探索共同點,結合微服務的思想,探索過程中對多端架構有了思想的摩擦,總結了一套業務介面與業務實現的規範,能夠更好地為其他業務提供服務。在此基礎上,將這一套規範運用在投放工程上,完成從舊架構的問題分析,到新架構的優化設計與實現的整個過程。從結果來看,模組的職責更為清晰,程式碼的許可權與邊界得到了比較好的控制,對以後業務的縱橫向擴充套件、程式碼的健壯性都有了質的保障。

 

參考連結

  1. https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84

  2. https://zh.wikipedia.org/wiki/MVC

  3. https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

  4. https://docs.gradle.org/current/userguide/dependency_types.html

 

免費領取驗證碼、內容安全、簡訊傳送、直播點播體驗包及雲伺服器等套餐

更多網易技術、產品、運營經驗分享請點選

 

相關文章:
【推薦】 如何做好iOS應用安全?這有一把行之有效的“三板斧”