微服務(wù)架構(gòu)如何結(jié)合DevOps做好持續(xù)交付
微服務(wù)架構(gòu)如何和持續(xù)交付過程相結(jié)合,是我們在實施微服務(wù)架構(gòu)的時候必須要考慮的問題,如果是一個簡單的單體應(yīng)用的自動化編譯構(gòu)建和發(fā)布,相對來說要簡單的多,但是在實施微服務(wù)架構(gòu)后,整個持續(xù)交付過程本身會增加一定的復(fù)雜度。
我們舉一個供應(yīng)鏈系統(tǒng)開發(fā)的場景來說明。
該供應(yīng)鏈系統(tǒng)劃分為了門戶應(yīng)用,招投標(biāo)中心,采購中心,供應(yīng)商中心,用戶中心和流程中心幾個大的微服務(wù)模塊?;谖⒎?wù)架構(gòu)本身進(jìn)行模塊拆分的要求可以看到,以上的六個微服務(wù)模塊要做到完全的獨立自治,獨立的配置管理庫,并能夠獨立進(jìn)行編譯構(gòu)建打包測試和最終的版本發(fā)布操作,而最終的六個微服務(wù)模塊一起組成一個完整的供應(yīng)鏈管理業(yè)務(wù)應(yīng)用。
這個和多年前我們談到的私有云PaaS平臺里面的組件化開發(fā)思路是完全一樣的?;谶@種微服務(wù)模塊劃分,我們來看如何和持續(xù)交付過程和DevOps支撐平臺相結(jié)合。
每個微服務(wù)模塊獨立進(jìn)行配置和源代碼管理,獨立數(shù)據(jù)庫,獨立進(jìn)行編譯構(gòu)建和部署發(fā)布。
在這種思路下可以看到,我們首先要有應(yīng)用集的概念,即本次構(gòu)建的供應(yīng)鏈管理就是一個大的應(yīng)用集,但是這個應(yīng)用集下面卻可以有多個微服務(wù)模塊。整個思路是要先構(gòu)建一個獨立的應(yīng)用集,并規(guī)劃應(yīng)用集的版本。然后才是在應(yīng)用集下面創(chuàng)建6個獨立的研發(fā)項目版本,分別對應(yīng)上面的6個微服務(wù)模塊,并制定獨立的svn或git源代碼目錄分支。
針對每一個微服務(wù)模塊都要獨立創(chuàng)建編譯,構(gòu)建,發(fā)布等任務(wù),同時針對每一個微服務(wù)模塊創(chuàng)建一個獨立的從編譯構(gòu)建測試到發(fā)布的流水線任務(wù)作業(yè)。該流水線每觸發(fā)執(zhí)行一次,即可以完成該獨立的微服務(wù)模塊的自動化編譯構(gòu)建打包,自動化的代碼檢查測試并發(fā)布到測試環(huán)境進(jìn)一步供測試人員進(jìn)行測試。
每一個微服務(wù)模塊只部署到一個Docker容器里面,不再進(jìn)一步進(jìn)行組件拆分部署到多個Docker容器中。但是容器本身可以在后期進(jìn)行資源動態(tài)擴(kuò)展。即微服微模塊編譯構(gòu)建通過,打包制作鏡像到一個鏡像文件,并在后續(xù)對鏡像文件進(jìn)行部署。
問題是在實際的DevOps支撐里面,可以考慮將打包和鏡像制作過程隱含掉,畢竟用戶并不關(guān)心該過程。
對于6個微服務(wù)模塊間有接口調(diào)用,在前面我們思路里面是內(nèi)部6個模塊間的交互不用啟用API網(wǎng)關(guān)進(jìn)行交互,而直接走微服務(wù)架構(gòu)里面的服務(wù)注冊和配置中心即可。
在多模塊交互協(xié)同下,所有的微服務(wù)模塊在觸發(fā)自動編譯構(gòu)建并部署后都需要自動化單元測試,這里面最重要的就是對接口的單元測試,這種單元測試包括南向接口和北向接口兩個部分的內(nèi)容,只有兩部分單元測試都通過,該模塊本身才處于一種穩(wěn)定可測狀態(tài)。
自動化單元測試不通過應(yīng)該先開發(fā)進(jìn)行檢查并解決,因此在多模塊分工下更加應(yīng)該首先對規(guī)劃好的接口進(jìn)行實現(xiàn)并發(fā)布,只有這樣才不會影響到其它模塊的并行開發(fā)工作。
最近我一直在思考,如果將整個持續(xù)交付過程規(guī)劃為研發(fā)過程管理工具和DevOps支撐平臺工具兩個工具平臺來支撐的話,實際上很多內(nèi)容很難在兩個平臺間協(xié)同好。DevOps平臺更多是技術(shù)平臺,僅僅解決的是構(gòu)建和發(fā)布過程,而實際上很難去解決我們說的多個組件間的協(xié)同和研發(fā)過程管理。
開發(fā)人員和測試人員,一種思路是測試人員手工執(zhí)行流水線,在執(zhí)行完成后進(jìn)行測試操作;還有一種思路是開發(fā)人員去跑流水線,在自測沒有問題后提交測試??梢钥吹礁玫淖龇☉?yīng)該是開發(fā)去跑流水線,提交測試后選擇已經(jīng)完成的需求或修復(fù)的Bug,自動變更狀態(tài)。而測試人員只需要在測試環(huán)境對待驗證的問題進(jìn)行測試和驗證就可以了。即只有問題狀態(tài)是待驗證,那么當(dāng)前的測試環(huán)境版本一定就是可以驗證的一個版本。
開發(fā)人員的流水線為:
代碼更新-》編譯構(gòu)建-》代碼檢查-》鏡像打包-》部署-》自動化單元測試-》人工驗證并提交測試
在人工驗證后提交測試,同時對相關(guān)需求和Bug的狀態(tài)進(jìn)行變更。測試人員可以進(jìn)入到測試環(huán)節(jié)。實際上我們大部分重復(fù)迭代都應(yīng)該在這個階段,直到所有的需求全部實現(xiàn),所有的Bug缺陷都關(guān)閉。
而基于上篇文章思考,在該流水線上可以再增加一個測試驗證環(huán)節(jié),即測試驗證通過后自動進(jìn)行環(huán)境遷移,將最新的版本發(fā)布到UAT環(huán)境以方便進(jìn)行UAT測試操作。如果考慮到流水線松耦合,那么可以將測試驗證后發(fā)布UAT環(huán)境作為一個獨立的流水線,即:
選擇鏡像(可以選擇多個鏡像)-》配置修改-》發(fā)布生產(chǎn)環(huán)境
在這個過程中鏡像從鏡像庫選擇,對應(yīng)到當(dāng)前項目的最新基線版本(基線版本為測試通過后的版本),即在開發(fā)流水線上仍然需要增加了一個打基線標(biāo)簽的人工操作,這個可以由測試人員來完成。
開發(fā)構(gòu)建,發(fā)布和SIT測試是單微服務(wù)模塊視角。但是整體的應(yīng)用版本規(guī)劃,UAT測試則是全應(yīng)用集視角。即不論是新增還是后續(xù)變更版本的規(guī)劃,我們都希望能夠看到整個應(yīng)用集的視角,包括這次變更究竟影響到哪些微服務(wù)模塊,哪些會重新構(gòu)建或發(fā)生版本變化,這些都必須清楚。
如果一個功能變更導(dǎo)致我們所有的微服務(wù)模塊都必須重新編譯構(gòu)建和發(fā)布,那么我們進(jìn)行微服務(wù)模塊拆分,按微服務(wù)方式獨立自治管理的目的就根本沒有達(dá)到。一個簡單的原則就是影響到哪個模塊就哪個模塊進(jìn)行更新,如果影響到接口,就接口對應(yīng)的模塊也配套更新??梢娢⒎?wù)模塊間的接口一定得松耦合,如果拆分為微服務(wù)模塊,但是之間的接口交互異常復(fù)雜,那么仍然是強耦合關(guān)系,沒有意義。
唯一需要說明的是一種變更是變動了底層基礎(chǔ)組件的接口規(guī)格,那么這種情況下往往才會出現(xiàn)大量的微服務(wù)模塊都出現(xiàn)重新編譯構(gòu)建?;A(chǔ)組件變更,如果接口沒有變更,那么上層的應(yīng)用組件同樣不應(yīng)該重新構(gòu)建,即相互之間應(yīng)該是基于服務(wù)接口的依賴,而不能是基于Jar包的依賴。Jar包依賴容易導(dǎo)致的問題就是在使用Maven的時候會觸發(fā)自動的重新編譯構(gòu)建操作。
從部署到DEV環(huán)境,再到部署到SIT環(huán)境,再到部署到UAT環(huán)境,整個過程必須進(jìn)行全程跟蹤。形成基于當(dāng)前項目版本的可視化追蹤視圖。這個功能實際在持續(xù)集成的時候也是必備的關(guān)鍵功能。