當持續集成遇上微服務:分治優于集中

crossjewelrs8 8年前發布 | 10K 次閱讀 微服務 持續集成 軟件架構

大師Martin Fowler對“ 持續集成 ”是這樣定義的: 持續集成是一種軟件開發實踐,即團隊開發成員經常集成他們的工作,通常每個成員每天至少集成一次,也就意味著每天可能會發生多次集成。每次集成都通過自動化的構建(包括編譯,發布,自動化測試)來驗證,從而盡快地發現集成錯誤。

當微服務產生后,持續集成也不得不被考慮起針對這種可以獨立部署的服務, 在數字化企業云平臺中有十四個微服務同時運行 ,如何建立起與之的映射,即微服務、CI構建與源碼的映射變得極為重要,如果還像簡單軟件那樣集中管理是否還行得通,那可能會是一場災難?在如此復雜的背景下,優良的持續集成方案同樣也會給我們帶來煥然一新的便利體驗。

碰撞的三種模式

1.一個代碼庫、一個CI構建

這種方式就是將所有的微服務放在同一個代碼庫中,并且使用一個CI構建。這么做唯一的好處就是只需要管理一個代碼庫,但隨之而來的麻煩會讓你應接不暇。

每當我們修改一個服務中的一行代碼后,我們必須重新構建所有的服務,所有的構建產物都是在同一個構建中完成。事實上其他的服務完全沒有重新構建的必要,這樣大大延長了上線速度。而在眾多構建物中要找出保證能夠讓你修改生效的服務來部署,也是足夠讓人頭疼了,這導致最終讓我們選擇重新部署所有代碼。再試想一下,所有人共享一個CI構建,每個人的修改都有可能造成CI的構建失敗,想要將這個CI構建成功穩定下來,頭痛又升級了,有沒有?

在眾所周知的谷歌使用的就是一個代碼庫,然而他們采用了自己的版本管理系統 “piper” 來管理超過20億行代碼的超級大庫,所以對于更多的小公司來說,這時谷歌就是一個特例。

在桌游盛行的年代有一款叫做 bucket king的桌游 ,每位玩家會被分到五種不同顏色的小桶,每種顏色有三個小桶,玩家必須以金字塔的形式堆疊起這些桶(即第一排5個第二排4個以此類推第五排1個)。游戲過程中當玩家沒有某種顏色手牌可出的時候必須抽掉一個相應顏色的桶,所有倒下的桶都會作廢。

說到這里大家想到了什么?是否很像我們一個代碼庫對應一個CI構建的持續集成模式?每種顏色的桶都是一個微服務,當我們某個微服務中的某一個環節出現了變動,我們的整個金字塔就變得不再完整,甚至出現崩潰。這個時候你想象每種顏色小桶分別堆成一個金字塔,分成五堆就可以了,這就像我們之前提到的采用多個CI構建。當然游戲規則是不允許玩家這么做的,但是持續集成是可以的。

2.一個代碼庫、多個CI構建

在這種方式中,代碼庫還是那個代碼庫,不過在代碼庫中我們創建了多個子目錄,每個子目錄對應一個CI構建。現在的很多項目中都會采取這種持續集成,這讓我們可以比較方便的同時提交對多個服務的修改。然而,來讓我們琢磨一下這種方式依舊會存在的弊端,隨著代碼修改的增加,無可避免的會在不經意間造成服務耦合度的增加,對不對?

我們來假設一下,在bucket king游戲中所有的桶都是一個代碼庫,允許我們將這些桶分成五個小金字塔,看上去我們降低了游戲的難度,但我們不能阻止玩家將不同顏色的小桶混搭。比如在一個2+1的紫色小金字塔中,玩家將底層的一個紫色小桶換成了藍色小桶,游戲進行到我們必須抽取掉一個藍色小桶,并且其他兩個藍色小桶已經“陣亡”了,這時候當我們抽取掉這個藍色小桶時,勢必使得上層的紫色小桶一起掉落。這就類似于一個代碼庫多個CI構建一樣。我們無法避免開發者在修改代碼過程中的耦合,當這些代碼出現問題的時候受到影響的絕對不會只有一個構建。

3.多個代碼庫、多個CI構建

每個微服務都有一個對應的代碼庫,每個代碼庫對應一個CI構建。這時候每個微服務變得獨立,修改運行部署不再相互依賴,大大降低了耦合度,方便了代碼的管理和維護。另外多代碼庫還給我們帶來另一個好處,就是共享問題,當你只有一個代碼庫的時候,如果想要共享,那必然所有代碼都必須共享,拆分多個代碼庫,這樣根據自己情況,你可以選擇性的共享代碼。當然,你又要說了,跨服務的修改變的麻煩了啊。沒錯,這也不是一個十全十美的方案,我們要做的就是選擇一個最佳方案,是不是?

所以,bucket king游戲中最理想的狀態就是我們規定五堆小金字塔必須為同種顏色不允許混搭,這時候即使三個藍色小桶全部“陣亡”也不會影響到紫色小桶。這就好比同種顏色的小桶是一個業務,由于微服務按照業務劃分即一個微服務對應一個業務,也就意味著每個微服務都是一個單獨的代碼庫,也對應一個CI構建。當然作為游戲它就失去了它的趣味性,不過類比到持續集成我們當然是要選擇對整體影響最小的方法。

我們的模式

針對微服務的持續集成,我們選擇多個代碼庫多個構建的方案。 當我們創建一個微服務時,會產生一個git代碼庫,雖然我們每個微服務可以創建多個版本,但是我們是不可以同時編輯多版本的,因為我們開發代碼是在git庫master支線上,當一個版本發布后我們會給這個發布的版本打一個分支,這時候我們才能編輯新的版本。所以我們的CI構建就映射到一個微服務版本中,每個微服務代碼提交代碼庫時會產生一個commitId,通常我們會針對這個commitId來進行一次構建,因此代碼庫分治也一定程度上避免了commitId不能與某個微服務對應的問題。 對于數字化企業云平臺的集成,每次構建編譯結束,產物就是一個完整的鏡像。

我們甚至想過可以選擇每個組件一個代碼庫,這樣做的好處就是更加細化的分治,使得我們編譯部署影響范圍更加縮小。

就微服務而言,筆者認為的最佳的實踐方案無疑是每個微服務對應一個代碼庫,每個代碼庫對應一個CI構建,分治遠遠好過于集中管理,你怎么看?

 

關于EAII

EAII(Enterprise Architecture Innovation Institute)企業架構創新研究院,致力于軟件架構創新與實踐,加速企業數字化轉型。

 

 

 

來自:http://mp.weixin.qq.com/s?__biz=MzI5MDEzMzg5Nw==&mid=2660393569&idx=1&sn=765054f03c90337b21aeb32ee5d6d718&chksm=f7424087c035c9915f75c4467b4d5af78d49bce52bee8cc4b5112be1e52abb9a0d73540fc131&scene=0

 

 本文由用戶 crossjewelrs8 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!