來源:《持續(xù)交付2.0》,作者 喬梁
信息的快速變化是我們這個時代的特點,誰能更快地捕捉和利用信息帶來的價值誰就能在競爭中占得先機,軟件發(fā)布和部署的頻率也因此被要求能夠跟上外部業(yè)務變化的速度,這種頻率已經(jīng)從以往的若干個月、若干個周進化到天、小時、分甚至是秒,這就好比一輛在高速公路上行駛的汽車,我們要一邊行駛還得一邊不停地更新車上的零部件。由此可見,為了能夠更好地應對業(yè)務發(fā)展,持續(xù)交付是必然趨勢,這一目標達成需要軟件架構按照“大系統(tǒng)小做”的原則進行設計和演進。
“大系統(tǒng)小做”原則
所謂“大系統(tǒng)小做”原則是指架構設計應該要考慮:
- 為測試而設計(design for test),在我接觸過的諸多項目里,測試過程(研發(fā)自測、集成測試、方案測試)絕對是一個時間消耗大戶,如果解決不了這個問題,那么快速發(fā)布和部署就是空談?;叵胛覀?nèi)粘5膱鼍按笾率沁@樣的:先花一些時間打包部署一個應用,然后開始測試,測試過程中發(fā)現(xiàn)了一個bug,分析了半天發(fā)現(xiàn)是一個簡單的錯誤。這還只是一個簡單的場景,如果涉及到多人、跨團隊、跨職能部門,那情況復雜的程度還會翻倍。那么為何不在寫代碼時就把這樣的錯誤給杜絕呢?很大原因就在于前期設計時埋下了隱患,沒有考慮“可測試性”??蓽y試性為什么如此重要?因為我們做設計,其實就是把一個軟件拆分成一個一個的小模塊。如果不盡可能地保證每個小模塊的正確性,而只是從最外圍的系統(tǒng)角度去驗證系統(tǒng)的正確性,這將會是一個非常困難的過程。
- 為部署而設計(design for deployment),部署耗時甚至需要停機已經(jīng)是不可接受的缺陷,部署的耗時是客戶能夠?qū)崒嵲谠隗w會到的,先人一步才存在調(diào)整的可能性,落后意味著挨打已經(jīng)不是什么商業(yè)秘密,同樣客戶也不會給你停機的窗口,停機將引發(fā)海量的用戶投訴和巨大的經(jīng)濟損失。
-
為監(jiān)控而設計(design for monitor),持續(xù)交付是一個不停滾動的過程,運維過程無時無刻不在發(fā)生,需要摒棄過往那種當問題發(fā)生之后才進行處理的做法,而是采取監(jiān)控的方式提前發(fā)現(xiàn)和消滅問題。InfoQ在“Software Architecture and Design InfoQ Trends Report—April 2021”
一文中也提到了可觀測設計是一種開始得到業(yè)界認可的設計思想。

- 為擴展而設計(design for scale),可擴展性不是一個新鮮的概念,這里擴展性包含兩個方面,一是支持團隊成員規(guī)模的擴展;二是支持系統(tǒng)自身的擴展。在云時代,擴展的概念有了更多的內(nèi)涵,架構上有了新的關注點:彈性邊界(Elasticity Boundary)。彈性邊界是云原生(Cloud Native)架構的核心概念,決定了我們是否能夠充分發(fā)揮云平臺的全部能力。
- 為失效而設計(design for failure),這是一種基于風險控制的架構設計,它思考的問題是“一旦部署或發(fā)布失敗,如何優(yōu)雅且快速地處理”,在很多產(chǎn)品設計中都可以看到降級處理的身影,這是一種非常典型的為失效而設計。
上述架構要求帶來的變化使人意識到原本一個單體應用包打天下的方法已經(jīng)有些不適用了,系統(tǒng)需要被拆分成更小的顆粒度,使其提升系統(tǒng)靈活性、可理解性并縮短開發(fā)時間,如何拆分才更合理呢?
- 組件或服務職責清晰,也是我們經(jīng)常說的SRP(單一職責原則);
- 高內(nèi)聚、低耦合,減少組件或服務獲知不相關信息的可能,其實也是我們在設計時會提到的ISP(接口隔離原則);
- 易于構建和測試,這兩點是實際生產(chǎn)活動最耗時的,不克服這兩點難題,無法做到“持續(xù)交付”;
- 使團隊成員之間的溝通協(xié)作更加順暢,換句話說就是組織架構必須適配軟件架構,這一點很關鍵也是常常被忽略的??低芍赋觥霸O計系統(tǒng)的組織其產(chǎn)生的設計等價于組織間的溝通結構”,如果我們希望持續(xù)地高效、高質(zhì)量地交付有價值的軟件產(chǎn)品,那么最終還是會把視線轉(zhuǎn)向軟件生產(chǎn)者,保證他們能獲得充足的資源,信息及其流通性是其中一種重要的資源。
盡管拆分有不少好處,但也意味著構建、測試、部署與監(jiān)測都需要隨之建立。每一個小系統(tǒng)都是一個自治系統(tǒng),都有完整的構建、測試、部署與監(jiān)測,這樣才能在獲得系統(tǒng)拆分的好處的同時又能把控住系統(tǒng)拆分而帶來的復雜性。
常見架構模式
基于上述的架構要求,我們有一些可以參考使用的架構模式。微核架構、微服務架構和巨石架構是三種比較常見的架構模式,它各有各的優(yōu)缺點,在不同的場景下均有應用,也都能支撐持續(xù)交付。
微核架構又叫插件架構,顧名思義,主要業(yè)務功能和業(yè)務邏輯都通過插件實現(xiàn),核心框架部分只包含系統(tǒng)啟動運行的基礎功能,顯然這種架構具備了:
- 功能擴展通過插件搞定
- 獨立地發(fā)布插件,還能獨立安裝與卸載
- 功能相互隔離,易于測試
- 可定制
- 可逐步地增加功能

插件化架構比較適合用于客戶端軟件,因此我們常用的Eclipse、IntelliJ IDEA、OSGi、Spring Plugin、SPI等都可以看作是插件化架構產(chǎn)品。
微服務架構是當下非常主流的一種架構模式,也是目前公司不少產(chǎn)品在使用的架構模式,它的主旨就是將單一應用劃分為一組小的服務,服務之間采用輕量級的通信機制,服務圍繞業(yè)務進行構建可以獨立地部署,不難看出微服務具有:
- 擴展性好,服務與服務低耦合,可以對單一服務進行擴容;
- 易部署
- 易開發(fā)
- 易測試
很多人把微服務架構看成是萬靈藥,認為所有的應用都應該考慮采用這種架構,這樣的想法是有問題的,微服務在提供上述的便利性的時候也會有問題,比如原子操作較困難,調(diào)用鏈長等。
Service Mesh(服務網(wǎng)格)被認為是下一代微服務架構,Service Mesh并沒有給我們帶來新的功能,它是用于解決其他工具已經(jīng)解決過的服務網(wǎng)絡調(diào)用、限流、熔斷和監(jiān)控等問題,只不過這次是在Cloud Native 的 kubernetes 環(huán)境下的實現(xiàn)。
巨石應用也叫單體式應用,巨石架構,也就是由單一結構體組成的軟件應用,這也是我們很常見的架構模式。當它被良好地設計、實現(xiàn)與守護時,就利于開發(fā)和調(diào)試,部署操作也很簡單,但它也通常是混亂代碼、學習困難、架構僵硬的代表。
巨石架構也能做到持續(xù)交付,關鍵點在于是否針對代碼的整個生命周期(開發(fā)、測試、部署)進行了良好的設計,否則即使是微服務這種對于持續(xù)交付天然合適的架構也會遭遇到持續(xù)交付困難的問題。
架構改造實施模式
當我們遇到了不好的架構時自然而然就需要進行改造,改造的過程有三種很形象的比喻:
- 拆遷者,就是對軟件架構重新設計,然后一次性替換原有系統(tǒng);
- 絞殺者,保持原有遺留系統(tǒng)不變,開發(fā)新功能時,逐步使遺留系統(tǒng)失效,最終實現(xiàn)替換;
- 修繕者,將遺留系統(tǒng)的部分功能與其余部分隔離,以新架構進行單獨改善,改善同時,需保證與其他部分仍能協(xié)同工作,這種方式與絞殺者類似,但改造發(fā)生在系統(tǒng)內(nèi)部。就像我們在住的家中進行裝修那樣會做很多隔離、鋪墊,然后再去進行裝修。
這三種模式,最難是修繕者,需要對系統(tǒng)有很深的理解和抽象能力;最常用的是拆遷者,簡單易用,我自己就干過拆遷者的活;比較主流的是絞殺者,非常適合作為從單體系統(tǒng)向微服務遷移的策略。
絞殺者主張通過用新服務替換特定功能來將單體系統(tǒng)逐步轉(zhuǎn)換為微服務,一旦新服務已經(jīng)能夠代替原有舊有功能,就將原有功能組件絞殺(即徹底停用)?;诮g殺者模式將單體系統(tǒng)拆分為微服務的時候,任何新的開發(fā)都應該作為新服務的一部分而不是單體系統(tǒng),這保證了新的開發(fā)領域的代碼具有較高的質(zhì)量。
借助絞殺者模式從單體系統(tǒng)向微服務系統(tǒng)遷移可以大致簡化為三個步驟,即轉(zhuǎn)化、共存和消亡。簡而言之,就是開發(fā)一個新組件(即微服務),讓新組建和舊組件共存一段時間,最終消除舊組件。大致步驟如下:
- 最初,所有訪問應用的流量都路由到舊版系統(tǒng);
- 構建新組件后,可以對單體系統(tǒng)代碼與新功能一起進行測試;
- 單體系統(tǒng)和新組件需要共同運行一段時間,這段過渡時間可能會較?,對新組件進行增量開發(fā)和測試后,可以完全停用舊的單體系統(tǒng)。
改造的過程還可以結合當下主流的架構設計方法DDD展開,我們可以先通過系統(tǒng)痛點分析,如代碼壞味道、系統(tǒng)或組件的耦合,發(fā)現(xiàn)我們要修訂的問題;再利用DDD提供的方法(統(tǒng)一語言、事件風暴等)對遺留系統(tǒng)建模;當DDD模型代碼合入的時采用絞殺者模式,最后在建立架構度量進行持續(xù)地守護。這樣的一套流程是許多互聯(lián)網(wǎng)企業(yè)改造他們架構的標準做法,也是值得我們學習和借鑒的。
總結
第5章“持續(xù)交付的軟件系統(tǒng)架構”探討了持續(xù)交付對于軟件架構的要求,即考慮可測試、易部署、可監(jiān)測、可擴展以及失效處理,并且把一些系統(tǒng)架構拆分的原則“大系統(tǒng)小做”進行了強調(diào),包括了職責清晰、高內(nèi)聚低耦合、易構建與測試以及架構相匹配的組織架構,這些都是我們在設計階段需要考慮的關鍵點,也是影響軟件持續(xù)交付的關鍵點。