在業務開發的過程當中,每每存在平臺代碼和業務代碼耦合嚴重難以分離、業務和業務之間代碼交織缺乏拆解的現象。平臺和業務代碼交織致使不易修改,不一樣業務的代碼交織增長了不一樣負責團隊之間的協同成本。所以不論從代碼質量,仍是從團隊協做的角度來看都嚴重地影響了開發團隊之間的協同效率和開發效率,最終影響到了用戶體驗和業務發展。在閒魚,商品發佈和編輯功能也是如此。本文將以閒魚商品發佈和編輯功能的改造爲例,向你們展現閒魚是如何解決此類問題,從而更有效地協同更多團隊更快更穩定地支撐各類業務的。html
爲了實現上述目標,針對發佈和編輯功能,進行了兩輪升級。第一輪的目標在於「平臺和業務分離、業務和業務隔離」;而第二輪將更進一步,目標在於「系統之間的解耦合,提高團隊協同效率」。緩存
1.平臺和業務分離,業務和業務隔離安全
第一輪改造中,閒魚將原先的商品發佈和編輯功能從老應用中抽取到了新應用item。爲了實現「平臺和業務分離、業務和業務隔離」的目標,閒魚自研了一套技術框架SWAK,具體請參考文章《業務代碼解構利器--SWAK》,該文介紹了其設計思想和實現原理。接入SWAK框架後,平臺邏輯和業務邏輯獲得了分離,各個業務(如租房業務、免費送業務)之間的邏輯也再也不耦合,而是變成package隔離(固然也是能夠作成jar包隔離)。網絡
看一看改造後的應用狀況示意圖:框架
根據這樣的開發方式,咱們能夠把開發同窗分紅以下的兩種角色:異步
如在以前的《業務代碼解構利器--SWAK》一文中指出的同樣,通過SWAK改造後,得到了以下的幾個優勢:性能
- 代碼邏輯清晰,可變和不可變一目瞭然。
2.系統之間的解耦合,提高團隊協同效率測試
以租房爲例——租房業務的同窗須要在item應用中維護一套租房發佈編輯相關的邏輯(如校驗地小區數據、地鐵數據真實性等);租房業務的同窗還須要在詳情應用的邏輯中維護一套和租房詳情相關的邏輯(如展現地圖,展現內部設施標籤);租房業務的同窗還須要在交易應用的邏輯中維護一套和租房交易相關的邏輯(如預定看房)等等。租房的同窗不只僅須要着手於本身的代碼邏輯,還須要修改發佈和編輯應用item、還須要修改詳情應用,還須要修改交易應用......這種體驗是很是糟糕的,有極大的可能性接手一個簡單業務就須要修改和發佈四五個應用。spa
另外一方面,從主幹開發人員的角度來講,其應用不只僅由本身或本身的小團隊來維護,還有不少業務開發人員也在修改和發佈此應用,且頻率會遠遠超過主幹開發任務的發佈和部署頻次(不然就是主幹擴展點邏輯抽取得很差了)。這不利於整個應用的穩定性。A業務服務掛了,應該隻影響A業務,而不該該影響主幹。依此邏輯,最好能作到JVM隔離。本質上來講,第一輪改造完成了業務之間的解耦合,而第二輪則是系統之間的解耦合。線程
康威定律告訴咱們:
Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization's communication structure.
簡而言之就是人員組織結構和系統結構之間的一致性。而完成系統之間的解耦合又偏偏是符合康威定律的。這一輪的改造,咱們稱之爲「業務服務化」。
經過這種方式,咱們將主幹應用和各業務應用完全分離了。仍然以租房業務爲例,租房團隊負責開發和維護租房業務的獨立應用rent。租房個性化的發佈和編輯需求只須要開發和部署rent應用,而沒必要修改主幹應用。主幹應用只由主幹團隊的同窗負責維護,不會被其餘業務團隊的同窗所開發和部署,穩定性更加能得以保障。各業務系統獨立開發、獨立部署。這些都大幅地減小了沒必要要的溝通成本、提高協同效率。
主幹應用和業務應用是經過薄薄的一層接口所聯繫起來的,這層薄薄的接口都是「聲明」:Interface定義、DO的定義和擴展點的默認Reduce策略定義。
SWAK框架的針對性改進
在以前的《業務代碼解構利器--SWAK》一文中指出了,SWAK框架在應用啓動的時候會經過各類註冊器(registery)註冊框架所需的信息。其中最重要的信息就是——業務tag及其對應的SWAK接口的實現類類名或者類實例instance。大多RPC框架都會在client端提供一個代理,代理掉內部的服務發現、保活、序列化、網絡通訊、反序列化等一系列操做。實際上,SWAK爲了支持遠程服務調用,只須要將業務tag,以及這些RPC的client的instance的對應關係註冊進去就能夠了。在閒魚,RPC使用的是阿里通用的HSF框架(其相似的一個開源框架是Dubbo),這裏的RPC的client就是HSF中的ConsumerBean。
上文還提到了RPC調用會引入服務超時、鏈接異常的概念。爲什麼要限制超時?是由於不能被單個應用的超時佔據了主幹應用的服務資源而引發其餘服務和整個應用系統受到影響(如大多數線程阻塞在超時調用上)。不管是超時異常仍是鏈接異常,在業務上也有對應的處理策略。在這裏,咱們定義了三種異常處理策略,經過在配置上設置相應的註解,SWAK框架會自動按照策略來處理異常。這三種策略是:
減小擴展點數量
衆所周知,RPC調用相對於本地調用會增長一部分的網絡傳輸和序列化開銷。對於單次調用來講,增長若干ms並無什麼問題,但對於調用10次、20次或更多,這筆開銷就至關可觀而應該引發重視了。爲此,如何下降RPC開銷,是一個必需要考慮的問題。
最可靠的方法就是下降RPC的次數。
在實踐中咱們發現,不少擴展點實際上都是獲取業務配置。如在閒魚業務中,「是否支持多庫存」就是一種配置,如租房不支持多庫存。這些業務配置項是由其業務形態所決定的,基本不會變更。所以能夠將一組配置項打包一塊兒調用,而且能夠緩存下來,也能夠直接由主幹應用進行維護。在item應用裏,這些配置項關係到主幹的通用存儲過程,目前由各業務方委託主幹開發人員進行維護,目前配置在主幹環境。能夠經過阿里的動態配置平臺(如Switch、Diamond)進行動態修改。
另外咱們對部分鄰接的擴展點進行了合併。這些相鄰擴展點之間的邏輯比較簡單,且不會中斷主流程。經過「配置型接口」和「鄰接擴展點合併」這兩種操做,咱們將擴展點數量下降由17個下降到了6個。要注意的是,擴展點並非越少越好。擴展點越少,越意味着「過分擬合」,可能會對後續業務變動沒法適應致使主幹須要大幅改動,所以須要在數量和擴展性之間找到一個平衡。
另外值得一提的是,SWAK爲配置型擴展點作了相應的小改造,並提供了查看當前配置型擴展點返回值的可視化界面。開發人員能夠直觀地瞭解當前各個業務的配置值。
接口對象定義和細節設計
在閒魚,各類業務所須要存儲的東西大同小異,從閒魚的發佈界面上來看就不難發現這一點,都是在基礎對象(如標題、描述、圖片)以外添加一些業務相關的數據,如拍賣業務中指定拍賣的開拍時間等信息,免費送業務中設置兌換幣值,圖書業務上設置條形碼。即對一本圖書進行拍賣固然也是容許的,這就出現了拍賣業務和圖書業務疊加起來的複合型業務。
對於主幹應用開發人員來講,應該提供單個接口以支持全部業務類型,這樣不用每次修改或者新增業務時都須要提供新接口。從穩定性的角度考慮,這樣的要求很合理。既然是單個接口,那麼DO的定義也應該統一。以商品DO爲例,有如下三種方式:
使用第三種的對象模型,以新加一種業務爲例,其開發流程是:
業務應用在擴展點返回值中設置須要更新的數據,由主幹應用合併。業務應用不該該也不能夠直接修改ItemDO,避免影響其餘業務的處理邏輯。對於發佈和編輯這種須要持久化存儲的邏輯來講,必需要強控各業務對ItemDO的修改,不然理論上來講,各業務都有可能將全部的關鍵字段修改得面目全非。前面提到的「配置型接口」中,就有這樣的配置——該業務是否能夠修改屬性字段、該業務是否能夠修改描述字段等配置。
閒魚的商品發佈和編輯功能基於SWAK框架通過了兩次改造升級,第一次升級完成了平臺和業務之間的解耦合以及業務和業務之間的解耦合,第二次升級經過平臺和業務間使用RPC調用完成了系統和系統之間的解耦合。改造以後,能更有效地協同更多團隊更快更穩定地支撐各類業務。SWAK框架依然在繼續演進,如部分擴展點原則上能夠經過並行處理或異步化處理來提高性能,但暫時尚未提供支持。在這兩次改造中, 咱們還在測試用例的採集、回放、監控告警等方面也有不少積累,敬請期待後續的文章分享。
本文爲雲棲社區原創內容,未經容許不得轉載。