從既有系統(tǒng)到微服務(wù)架構(gòu)

微服務(wù)近年來可謂炙手可熱,合理的使用微服務(wù)架構(gòu)可以解耦系統(tǒng)、提供更好的軟件伸縮性以及提高組織的敏捷性。然而現(xiàn)實(shí)中較少有項(xiàng)目一開始就會(huì)選擇使用微服務(wù)架構(gòu),絕大多數(shù)新項(xiàng)目在最初都會(huì)務(wù)實(shí)地從更容易掌控的單體架構(gòu)起步構(gòu)建,如果最終發(fā)現(xiàn)單體架構(gòu)復(fù)雜到影響了團(tuán)隊(duì)的開發(fā)效率及軟件的伸縮性等方面時(shí),才會(huì)開始考慮逐步將系統(tǒng)往微服務(wù)架構(gòu)做演進(jìn)。

現(xiàn)實(shí)中任何軟件架構(gòu)都是諸多trade-off的結(jié)果,想要獲得微服務(wù)架構(gòu)所帶來的好處也就意味著有能力承擔(dān)它所帶來的的副作用。Martin Fowler就曾在MicroservicePrerequisites一文中指出實(shí)施微服務(wù)所需要的先決條件,他用“個(gè)子是否夠高”形象地比喻了微服務(wù)所需的技能門檻。

而對(duì)于既有系統(tǒng),還需要一種務(wù)實(shí)的演進(jìn)方法和實(shí)施策略,使得能夠伴隨著恰當(dāng)?shù)拇a重構(gòu),逐步積累能力和完善基礎(chǔ)設(shè)施,最終平穩(wěn)的將其演進(jìn)到微服務(wù)架構(gòu)。

本文總結(jié)了一些從既有系統(tǒng)到微服務(wù)演進(jìn)之路上會(huì)遇到的問題和解決策略。文中使用“既有系統(tǒng)”而非“遺留系統(tǒng)”,是因?yàn)檫z留系統(tǒng)給人一種即將退出生命周期、行將就木的感覺,而我們則希望把精力投入到還有長(zhǎng)遠(yuǎn)商業(yè)價(jià)值的系統(tǒng)上,通過合理的微服務(wù)演進(jìn)讓其具有持續(xù)的生命力。

演進(jìn)策略

本文推薦的從既有系統(tǒng)到微服務(wù)的一種務(wù)實(shí)安全的演進(jìn)策略是:自上向下分析,自下向上重構(gòu),逐步完善配套

所謂“自上向下分析”,主要包含以下步驟:

  • 整體演進(jìn)路線規(guī)劃:

    • 梳理既有系統(tǒng)的領(lǐng)域模型,設(shè)計(jì)合理的內(nèi)部服務(wù)邊界,按照優(yōu)先級(jí)和依賴關(guān)系規(guī)劃演進(jìn)路線;
  • 服務(wù)治理方案設(shè)計(jì):

    • 按照優(yōu)先級(jí),為新服務(wù)定義職責(zé),接口,與既有系統(tǒng)的交互方式以及跨服務(wù)的集成測(cè)試方案;
    • 定義新服務(wù)的打包、測(cè)試、發(fā)布、部署、集成方式,目標(biāo)是能夠?yàn)槠錁?gòu)建獨(dú)立的代碼庫(kù)和持續(xù)交付流水線;
  • 代碼解耦設(shè)計(jì)和重構(gòu):

    • 分析屬于新服務(wù)的獨(dú)立代碼以及和既有系統(tǒng)耦合的代碼,從物理打包和邏輯代碼重構(gòu)兩層面解決耦合問題;
    • 針對(duì)不同的解耦策略,制定不同的測(cè)試策略,完善自動(dòng)化測(cè)試以支撐對(duì)應(yīng)的代碼重構(gòu)工作。

所謂“自下向上重構(gòu)”,指的是按照前面的分析設(shè)計(jì)結(jié)果,從代碼重構(gòu)開始,自下向上按照優(yōu)先級(jí)和一定節(jié)奏持續(xù)進(jìn)行服務(wù)化改造。

而“逐步完善配套”,指的是隨著服務(wù)化的開展,逐步完善代碼庫(kù)管理,多流水線集成,并逐步按需引入服務(wù)治理框架,積累微服務(wù)需要的技術(shù)和工具能力。

上述過程是一個(gè)迭代的過程:通過適度的分析和設(shè)計(jì),規(guī)劃出具體的落地工作,然后通過小步增量的實(shí)踐迅速獲得成果和反饋,在過程中逐步培養(yǎng)人的能力、完善支撐微服務(wù)架構(gòu)的工程實(shí)踐。

自上向下設(shè)計(jì)

明確目標(biāo)和約束

對(duì)既有系統(tǒng)做微服務(wù)化解耦,需要對(duì)不同解耦方向能獲得的收益和存在的約束做到心中有數(shù)。見過一些組織在做微服務(wù)拆分時(shí)只強(qiáng)調(diào)可以獲得的片面好處,忽略了對(duì)組織更有益的其它潛在價(jià)值,或者低估了微服務(wù)化帶來的問題。這往往會(huì)導(dǎo)致不合理的服務(wù)邊界劃分或者錯(cuò)誤的優(yōu)先級(jí)排序。

沿著不同的邊界劃分,目的是為了不同的價(jià)值目標(biāo):

  • 沿著系統(tǒng)內(nèi)不同的變化原因和變化頻率做服務(wù)劃分
    通過隔離不同的變化方向,減少特性開發(fā)之間的干擾,使能小的獨(dú)立交付團(tuán)隊(duì)。通過獨(dú)立代碼庫(kù)、獨(dú)立流水線,獨(dú)立的開發(fā)、測(cè)試、交付和運(yùn)維過程,提高交付效率和響應(yīng)速度。

  • 沿著不同的資源使用邊界做服務(wù)劃分
    通過將不同資源占用特征的服務(wù)進(jìn)行隔離,使能獨(dú)立的水平彈縮,優(yōu)化資源使用效率和提升業(yè)務(wù)響應(yīng)能力。

  • 沿著不同性能路徑邊界做服務(wù)劃分
    通過將性能核心路徑作為獨(dú)立服務(wù)進(jìn)行隔離,可以為性能核心路徑使用不同的技術(shù)棧以及做各種極致的性能優(yōu)化;另一方面避免各種改動(dòng)影響到關(guān)鍵路徑的性能下降(例如被動(dòng)引入更多的異步交互等)。

由于服務(wù)劃分會(huì)為系統(tǒng)引入新內(nèi)部邊界,所以必須考慮如下的約束:

  • 數(shù)據(jù)一致性約束:服務(wù)劃分后可能帶來數(shù)據(jù)一致性變?nèi)醯膯栴},需要考慮是否可以接受;

  • 性能約束:服務(wù)劃分后帶來的潛在性能下降,需要考慮如何度量以及承受程度;

  • 容錯(cuò)性約束:服務(wù)劃分為系統(tǒng)內(nèi)部引入更多的分布式故障點(diǎn),需要能夠?yàn)槠湔业娇山邮艿娜蒎e(cuò)設(shè)計(jì);

  • 耦合關(guān)系約束:服務(wù)劃分會(huì)放大系統(tǒng)的耦合問題,所以需要考慮沿著系統(tǒng)的松耦合邊界進(jìn)行服務(wù)劃分,避免服務(wù)間復(fù)雜的交互或者聯(lián)動(dòng)修改。

在開始可以按照理想的價(jià)值目標(biāo)去劃分微服務(wù)邊界,然后再接受每一項(xiàng)約束的挑戰(zhàn),最終的服務(wù)劃分方案往往是一個(gè)在目標(biāo)和約束之間逐漸平衡后的結(jié)果。

避免過度設(shè)計(jì)陷阱

對(duì)既有系統(tǒng)的微服務(wù)改造設(shè)計(jì)往往會(huì)陷入“架構(gòu)設(shè)計(jì)陷阱”。過于詳盡的分析和設(shè)計(jì)反而常常會(huì)阻礙微服務(wù)的拆分,經(jīng)常得到一個(gè)“成本很大,困難很多”的論證。

對(duì)于這種情況,建議采用 快速啟動(dòng)、增量交付、大膽實(shí)驗(yàn)、小心求證 的原則。即快速構(gòu)建目標(biāo),通過敏捷和精益軟件開發(fā)的方式快速實(shí)踐,通過反饋進(jìn)行快速學(xué)習(xí),在行動(dòng)中解決各種問題。

具體的實(shí)踐過程中:

  • 有了基本的分析后,快速成立試點(diǎn)團(tuán)隊(duì)作為探索者進(jìn)行解耦驗(yàn)證,盡早獲得反饋;
  • 雖然快速啟動(dòng),但是短期目標(biāo)要明確,通過迭代的增量交付來規(guī)避風(fēng)險(xiǎn);
  • 在實(shí)踐過程中逐步按需對(duì)修改影響較大的特性補(bǔ)充和完善自動(dòng)化測(cè)試;
  • 對(duì)有較大風(fēng)險(xiǎn)的代碼修改,可以先拷貝一份在新的服務(wù)內(nèi)做實(shí)驗(yàn),獲得足夠反饋后再擇機(jī)合入原代碼庫(kù);
  • 可以借助工具分析代碼的依賴關(guān)系。曾經(jīng)在一個(gè)項(xiàng)目我們通過部署doxygen和graphviz來可視化代碼的依賴關(guān)系和解耦進(jìn)展,取得了不錯(cuò)的效果。

微服務(wù)設(shè)計(jì)

關(guān)于微服務(wù)設(shè)計(jì)的方方面面已經(jīng)有很多優(yōu)秀的書和文章了,例如《微服務(wù)設(shè)計(jì)》就是一本不錯(cuò)的教材。即便如此到任何一個(gè)具體的領(lǐng)域,仍有很多困難和挑戰(zhàn),需要領(lǐng)域?qū)<液蛙浖こ處焸兠芮信浜先ソ鉀Q。

使用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)方法可以幫助所有參與者重新梳理業(yè)務(wù)并達(dá)成共識(shí)。通過識(shí)別業(yè)務(wù)的界定上下文和聚合根,可以為如何劃分服務(wù)提供參考。可以嘗試組織DDD Workshop,但是要清楚這只是一項(xiàng)工具,而且有時(shí)成本并不小。DDD是一個(gè)演進(jìn)式的過程,更多的工作需要隨著深入業(yè)務(wù)和代碼,通過實(shí)踐收集反饋迭代式的進(jìn)行。

現(xiàn)實(shí)情況中,負(fù)責(zé)系統(tǒng)架構(gòu)演進(jìn)的人員都是對(duì)業(yè)務(wù)和設(shè)計(jì)現(xiàn)狀比較熟悉的專家,一種高效的做法是從當(dāng)前的數(shù)據(jù)模型直接入手。分析每一張表和每項(xiàng)字段所支撐的業(yè)務(wù),將業(yè)務(wù)按照數(shù)據(jù)的內(nèi)聚性進(jìn)行分類,然后以此作為服務(wù)劃分的起點(diǎn)??梢约僭O(shè)已經(jīng)將數(shù)據(jù)按照新的服務(wù)邊界重新分庫(kù)分表,然后嘗試基于此重新構(gòu)建每條業(yè)務(wù)流程,并在過程中解決由于數(shù)據(jù)拆分而出現(xiàn)的各種問題。該做法適合對(duì)微服務(wù)架構(gòu)有經(jīng)驗(yàn)的人和領(lǐng)域?qū)<液献魍瓿桑@樣能夠?qū)Τ霈F(xiàn)的各種問題找到不偏頗的解決方案。

天下沒有免費(fèi)的午餐,有時(shí)為了得到微服務(wù)的好處,是需要做一些妥協(xié)的。例如數(shù)據(jù)模型中某一實(shí)體的不同屬性具有不同的業(yè)務(wù)內(nèi)聚度,所以同一概念的不同屬性數(shù)據(jù)被分到了不同服務(wù)中,但是這些數(shù)據(jù)在某些場(chǎng)景下要保持同步(例如需要被整體刪除或修改等)。最常見的解決方案是選擇一個(gè)穩(wěn)定的服務(wù)作為對(duì)該實(shí)體的權(quán)威擁有者,其它服務(wù)通過某種手段(例如消息隊(duì)列)和該服務(wù)對(duì)齊各種實(shí)例操作。這意味著業(yè)務(wù)要能接受最終一致性,還得接受在某些異常場(chǎng)景下數(shù)據(jù)一直沒有同步成功而上報(bào)的告警。

在設(shè)計(jì)服務(wù)的集成方式時(shí),需要站在業(yè)務(wù)角度去識(shí)別誰是更穩(wěn)定的服務(wù)。依據(jù)“向穩(wěn)定方向依賴”的原則,我們只會(huì)讓不穩(wěn)定的服務(wù)去調(diào)用穩(wěn)定服務(wù)的API,而反過來穩(wěn)定的服務(wù)最好通過消息隊(duì)列發(fā)布事件。那些需要跨越多個(gè)服務(wù)去獲取數(shù)據(jù)的服務(wù),一般可以通過監(jiān)聽事件和緩存與系統(tǒng)解耦,但這并非適合所有場(chǎng)景。在某些場(chǎng)景下由于業(yè)務(wù)的一致性和性能限制,我們確實(shí)需要往回退,把某些服務(wù)進(jìn)行合并。這就是個(gè)不斷的頭腦風(fēng)暴,然后再在各種選擇中做trade-off,最終獲得平衡的過程。

對(duì)于缺乏經(jīng)驗(yàn)的團(tuán)隊(duì)可以從較容易拆分的服務(wù)做起。例如一個(gè)web服務(wù)端可以先把路由和基本鑒權(quán)拆分出來,交給API Gateway負(fù)責(zé);然后再把各種報(bào)表和統(tǒng)計(jì)等一致性與性能要求相對(duì)低的拆分出來,最后再嘗試切分其它業(yè)務(wù)處理。

一旦服務(wù)拆分出來,就可以根據(jù)業(yè)務(wù)特征重新優(yōu)化數(shù)據(jù)模型并選擇更適合的數(shù)據(jù)庫(kù)。另外服務(wù)的API設(shè)計(jì)也是有技巧的:應(yīng)用接口隔離原則,需要API能獨(dú)立完成功能,又要粒度相對(duì)小可以靈活組合。這方面亞馬遜各種AWS服務(wù)的API設(shè)計(jì)就是不錯(cuò)的樣例。

自下向上重構(gòu)

得到了可行的服務(wù)劃分方案,接下來就需要實(shí)際操作代碼,將新服務(wù)的代碼與既有系統(tǒng)進(jìn)行解耦,為獨(dú)立的服務(wù)代碼庫(kù)和流水線做好準(zhǔn)備。

目錄/包結(jié)構(gòu)調(diào)整

軟件的包結(jié)構(gòu)一般和構(gòu)建軟件的組織結(jié)構(gòu)以及建模方式有關(guān)。一般復(fù)雜系統(tǒng)同時(shí)存在著兩個(gè)大的變化方向:技術(shù)維度和業(yè)務(wù)維度,而軟件的包結(jié)構(gòu)往往只能反映其中的一個(gè)維度。當(dāng)組織結(jié)構(gòu)以軟件的技術(shù)維度進(jìn)行劃分,那么系統(tǒng)的包結(jié)構(gòu)也基本上會(huì)以此劃分,這時(shí)業(yè)務(wù)維度的變化往往會(huì)映射到系統(tǒng)的每一個(gè)包上。反過來也是一樣!衡量哪種包結(jié)構(gòu)合理,往往是看當(dāng)前哪個(gè)是主要的變化方向。對(duì)主要的變化方向進(jìn)行拆包隔離,可以降低代碼變化之間的互相影響程度。

如果按照變化方向進(jìn)行包的拆分,就會(huì)發(fā)現(xiàn)系統(tǒng)中應(yīng)該存在很多小的包,最后每個(gè)服務(wù)是一堆原子的小包組合。這本質(zhì)上是將系統(tǒng)重新進(jìn)行合理模塊化的過程。Adam Drake在文章Enough with the microservices中就直接指出微服務(wù)架構(gòu)應(yīng)該先從良好的模塊化重構(gòu)做起,大多數(shù)時(shí)候當(dāng)模塊化做好了甚至?xí)l(fā)現(xiàn)很多問題已經(jīng)得到解決了。

然而既有系統(tǒng)的模塊合理化調(diào)整很難僅通過重新拆包達(dá)成!因?yàn)榇a是有邏輯的,模塊化的邏輯邊界不可能剛剛好落在代碼文件邊界。大多數(shù)情況下都需要先對(duì)某一個(gè)代碼文件進(jìn)行拆分,對(duì)某一個(gè)類或者函數(shù)進(jìn)行重構(gòu),對(duì)某一段邏輯進(jìn)行重新設(shè)計(jì),然后才能重新得到一個(gè)一致的邏輯和物理邊界,支撐繼續(xù)的拆包工作。

之前見過一個(gè)組織通過拆包進(jìn)行系統(tǒng)解耦,他們把新服務(wù)和既有系統(tǒng)共享的所有代碼拆分成很多小的共享包。這樣做后看似每個(gè)服務(wù)在構(gòu)建和流水線是獨(dú)立性的,但是問題在于那些共享包的代碼量并不小而且包含很多耦合的業(yè)務(wù)邏輯,新的修改經(jīng)常導(dǎo)致新服務(wù)和既有系統(tǒng)一起升級(jí)更新。

可以先對(duì)新服務(wù)建立獨(dú)立的目錄,然后嘗試把屬于新服務(wù)的代碼逐漸往獨(dú)立目錄中遷移,在這一過程中識(shí)別出新服務(wù)和既有系統(tǒng)耦合的代碼,然后一邊重構(gòu),再一邊繼續(xù)調(diào)整目錄和包結(jié)構(gòu),最后使得新服務(wù)和既有系統(tǒng)在物理和邏輯上同時(shí)解耦。

代碼重構(gòu)

軟件重構(gòu)目的是為了解耦新服務(wù)和既有系統(tǒng)之間的共享代碼。共享代碼一般分為如下幾種形式:

  • 共同依賴的組件或者類,這又分為如下幾種情況:

    • 穩(wěn)定的基礎(chǔ)功能代碼。例如編解碼庫(kù),加解密等等。這些代碼可以按照功能發(fā)布成獨(dú)立組件,供每個(gè)服務(wù)自行決定使用。
    • 服務(wù)間接口和消息定義。這類代碼可以劃分到獨(dú)立的庫(kù)中,盡量保持向前兼容,由接口的消費(fèi)方自由選擇依賴的版本。服務(wù)間的API和消息定義在本質(zhì)上是契約的共享,可以使用契約描述文件代替共享代碼,使用時(shí)自動(dòng)從契約描述生成代碼,這對(duì)于不同技術(shù)棧的服務(wù)會(huì)比較友好。
    • 不合理編碼導(dǎo)致的耦合。例如耦合了所有功能的大而全的單例類,一般是一些全局配置類或者是“創(chuàng)建一切”的工廠類等。這種情況需要對(duì)原有設(shè)計(jì)進(jìn)行重構(gòu),對(duì)大而全的類進(jìn)行拆分,將屬于不同服務(wù)的代碼拆分到不同的類中,由各個(gè)服務(wù)領(lǐng)回屬于自己的代碼。
  • 共同繼承的接口或者類,這又分為如下幾種情況:

    • 繼承是為了組合:需要將繼承的公共處理重構(gòu)為支撐組件,由不同的服務(wù)根據(jù)需要自行選擇組合和使用方式。
    • 繼承是為了面向接口編程,這時(shí)接口往往是為了配合某些公共業(yè)務(wù)處理而做的抽象。這些公共處理可以按照以下幾種情況進(jìn)行重構(gòu):
      1. 接口背后的公共處理包含了復(fù)雜的業(yè)務(wù)邏輯,優(yōu)先考慮將該公共處理變?yōu)橐粋€(gè)服務(wù)。這時(shí)需要將繼承接口上的同步調(diào)用變?yōu)榉?wù)間的消息接口。
      2. 接口背后的公共處理簡(jiǎn)單或者并不穩(wěn)定,可以考慮按照“Replication Over Reuse”的原則,由每個(gè)服務(wù)自行實(shí)現(xiàn),減少服務(wù)間的代碼共享。
      3. 接口背后的公共處理復(fù)雜,但是包含的業(yè)務(wù)邏輯相對(duì)穩(wěn)定,如果不能將其獨(dú)立為服務(wù)(例如由于性能原因),可以將其打包成公共組件,由每個(gè)服務(wù)自行組合使用。

從既有系統(tǒng)到微服務(wù)演進(jìn),在具體的落地中會(huì)發(fā)現(xiàn)最基礎(chǔ)的工作主要是代碼重構(gòu)。而能否很好的實(shí)施代碼重構(gòu)是一個(gè)體現(xiàn)團(tuán)隊(duì)基本軟件技能素質(zhì)的過程,需要團(tuán)隊(duì)提升軟件設(shè)計(jì)、代碼重構(gòu)、自動(dòng)化測(cè)試方面的能力。

逐步完善配套

隨著自下向上的重構(gòu),新服務(wù)的代碼逐漸解耦到獨(dú)立的目錄或者包中,這時(shí)就可以按需補(bǔ)齊服務(wù)化所欠缺的服務(wù)治理機(jī)制和各種工程實(shí)踐。在服務(wù)代碼不具備獨(dú)立性的時(shí)候開始嘗試搭建各種服務(wù)治理機(jī)制和工程流水線,往往會(huì)引入很多偶發(fā)復(fù)雜度,對(duì)工具提出一些不切實(shí)際的要求。

服務(wù)治理

微服務(wù)作為面向服務(wù)架構(gòu)當(dāng)下能夠流行,原因之一在于隨著技術(shù)的進(jìn)步各種服務(wù)治理工具都可以廉價(jià)獲得。服務(wù)注冊(cè)發(fā)現(xiàn)、API網(wǎng)關(guān)、消息隊(duì)列、負(fù)載均衡、服務(wù)監(jiān)控、集群運(yùn)維等每種需求都可以在網(wǎng)絡(luò)上找到一批的開源工具,而團(tuán)隊(duì)則需要根據(jù)自己的現(xiàn)狀進(jìn)行合理的選擇。有經(jīng)驗(yàn)的團(tuán)隊(duì)可以把各種不同的治理工作交給最合適的工具去做,而對(duì)于缺乏經(jīng)驗(yàn)的團(tuán)隊(duì)來說可以先從某一工具入手累積經(jīng)驗(yàn)。曾經(jīng)有一個(gè)團(tuán)隊(duì)在開始不想引入過多工具復(fù)雜性,先選擇使用redis做緩存和消息隊(duì)列,隨后又使用redis做分布式配置以及服務(wù)的注冊(cè)與發(fā)現(xiàn)等等。后來隨著能力提升,轉(zhuǎn)而使用etcd替代redis做服務(wù)的注冊(cè)發(fā)現(xiàn),使用kafka做消息隊(duì)列。

對(duì)服務(wù)治理工具的選擇要避免陷入選擇困難癥。每個(gè)團(tuán)隊(duì)都會(huì)覺得自己的業(yè)務(wù)特殊,開源工具總是不能滿足自己的所有要求。帶著這種想法很容易裹足不前,一再浪費(fèi)架構(gòu)重構(gòu)的合適時(shí)機(jī)。精益的做法是,先找到業(yè)界普遍使用的工具,一邊使用一邊解決問題,一旦開始了很多問題在實(shí)踐中總能迎刃而解。對(duì)于一些注重性能的系統(tǒng),不可避免的需要對(duì)開源組件在特定業(yè)務(wù)場(chǎng)景下進(jìn)行優(yōu)化定制,也最好先開始使用然后在實(shí)踐中確定優(yōu)化的方向。

持續(xù)交付

“服務(wù)有自己獨(dú)立代碼庫(kù)和交付流水線,可以避免交付過程中的互相干擾,提高交付速度和質(zhì)量”,遺憾的是上述描述其實(shí)是個(gè)偽命題!

真正減少團(tuán)隊(duì)干擾、提高交付速度和質(zhì)量的是“正確的解耦”本身。獨(dú)立的代碼庫(kù)和流水線會(huì)將架構(gòu)約束顯示化,讓團(tuán)隊(duì)成員難以犯錯(cuò)。但是如果過早的對(duì)不成熟或者不穩(wěn)定的架構(gòu)邊界進(jìn)行固化,反而會(huì)降低團(tuán)隊(duì)的效率,讓后續(xù)架構(gòu)調(diào)整變得困難。另外在系統(tǒng)沒有合理解耦的情況下,獨(dú)立的代碼庫(kù)和流水線只會(huì)讓交互變得更復(fù)雜,導(dǎo)致對(duì)構(gòu)建和發(fā)布工具提出一堆不合理的要求。

但是如果服務(wù)之間確實(shí)已經(jīng)正交拆分,代碼邊界和架構(gòu)邊界一致并且是穩(wěn)定的,這時(shí)獨(dú)立的代碼庫(kù)和流水線就可以降低團(tuán)隊(duì)在交付流水線上的互相干擾和排隊(duì),此時(shí)就值得為新的服務(wù)建立獨(dú)立的代碼庫(kù)和自動(dòng)化流水線??紤]到服務(wù)之間的集成,往往需要多級(jí)流水線,這時(shí)選擇一款支持pipeline的持續(xù)集成工具是必要的。Jenkins2.x以及GoCD是此類產(chǎn)品的代表。

適應(yīng)的組織結(jié)構(gòu)和文化

康威定律經(jīng)常被拿來說明組織結(jié)構(gòu)和系統(tǒng)架構(gòu)之間的互相作用關(guān)系。在對(duì)既有系統(tǒng)的服務(wù)化重構(gòu)中,軟件架構(gòu)和團(tuán)隊(duì)結(jié)構(gòu)同步進(jìn)行調(diào)整會(huì)讓整個(gè)過程更加順暢。曾經(jīng)有一個(gè)系統(tǒng)最初按照技術(shù)維度劃分團(tuán)隊(duì),后來為了提高響應(yīng)市場(chǎng)的速度把團(tuán)隊(duì)按照不同的業(yè)務(wù)類型進(jìn)行了調(diào)整。重新劃分后的團(tuán)隊(duì)開始發(fā)現(xiàn)他們會(huì)經(jīng)常修改同一公共組件,這時(shí)他們自發(fā)的對(duì)該組件進(jìn)行了解耦,將其中和業(yè)務(wù)相關(guān)的邏輯各自領(lǐng)了回去,然后將剩下的穩(wěn)定邏輯下沉到了基礎(chǔ)設(shè)施中。

除了匹配的組織結(jié)構(gòu),還需要團(tuán)隊(duì)逐漸調(diào)整自己的文化。專門的測(cè)試人員和運(yùn)維人員在微服務(wù)架構(gòu)下必然成為瓶頸,需要改變傳統(tǒng)的細(xì)分工的文化。團(tuán)隊(duì)每個(gè)成員都要有意愿和能力承擔(dān)起服務(wù)的測(cè)試和運(yùn)維工作,這需要組織從文化建設(shè)到考核方式做對(duì)應(yīng)的調(diào)整。

總結(jié)

對(duì)于既有系統(tǒng)做微服務(wù)演進(jìn),一旦第一個(gè)服務(wù)改造成功,后續(xù)的服務(wù)借助前面的成功經(jīng)驗(yàn)和已有的基礎(chǔ)實(shí)施,會(huì)更加的容易拆分。不過第一個(gè)服務(wù)的拆分確實(shí)需要投入比較大的決心和精力,本文給出了一些建議,歸根結(jié)底總結(jié)起來就是:以精益的方式開展,以代碼解耦為核心,以服務(wù)化技能做武裝,以組織結(jié)構(gòu)和文化調(diào)整做基礎(chǔ)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容