引子
隨著領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)、持續(xù)交付习霹、按需虛擬化、基礎(chǔ)設(shè)施自動(dòng)化炫隶、小型自治團(tuán)隊(duì)淋叶、大型集群系統(tǒng)這些實(shí)踐的流行,微服務(wù)也應(yīng)運(yùn)而生——微服務(wù)不是被發(fā)明出來(lái)的等限,而是從現(xiàn)實(shí)世界中總結(jié)出來(lái)的一種趨勢(shì)爸吮。
微服務(wù)的第一步——高內(nèi)聚低耦合
低耦合:修改一個(gè)服務(wù)不需要修改另外一個(gè)服務(wù)。
能夠獨(dú)立修改及部署單個(gè)服務(wù)而不需要修改系統(tǒng)的其他部分望门,這是使用微服務(wù)最重要的一點(diǎn)形娇。一個(gè)松耦合的服務(wù)應(yīng)該盡可能少地知道與之協(xié)作的那些服務(wù)的信息,意味著應(yīng)該限制兩個(gè)服務(wù)之間不同調(diào)用形式的數(shù)量筹误,因?yàn)槌藵撛诘男阅軉?wèn)題之外桐早,過(guò)度的通信可能會(huì)導(dǎo)致高耦合。
高內(nèi)聚:把相關(guān)行為聚集在一起厨剪,把不相關(guān)行為放在別處哄酝。
如果我們要改變某個(gè)行為的話,最好能夠只在一個(gè)地方進(jìn)行修改祷膳,然后就可以盡快地發(fā)布陶衅。如果需要在很多不同的地方做修改,那么可能就需要同時(shí)發(fā)布多個(gè)微服務(wù)才能交付這個(gè)功能直晨。在多個(gè)不同的地方進(jìn)行修改會(huì)降低速度搀军,同時(shí)部署多個(gè)服務(wù)風(fēng)險(xiǎn)也很高,這兩者都是我們想要避免的勇皇。
所以罩句,找到問(wèn)題域的邊界就可以確保相關(guān)的行為放在同一個(gè)地方,并且它們會(huì)和其他邊界以盡量低耦合的形式進(jìn)行通信敛摘。
持續(xù)集成
什么是CI? 我們可以引用Jez Humble(《持續(xù)交付》的作者门烂,持續(xù)交付的書(shū)名來(lái)源于敏捷宣言的第一條原則:“我們的首要任務(wù)是盡早持續(xù)交付有價(jià)值的軟件并讓客戶滿意。”)提出的三個(gè)問(wèn)題用來(lái)測(cè)試我們是否真正理解CI屯远。
我們是否每天簽入代碼到主線蔓姚?
我們應(yīng)該保證代碼能夠與已有代碼進(jìn)行集成。如果我們的代碼和其他人的代碼沒(méi)被頻繁地放在一起慨丐,那么將來(lái)的集成就會(huì)非常困難赂乐。即使我們只使用生命周期很短的分支來(lái)管理這些修改,也要盡可能頻繁地把代碼撿入到單個(gè)主線分支中咖气。
我們是否有一組測(cè)試來(lái)驗(yàn)證修改?
如果沒(méi)有測(cè)試挖滤,我們只能知道集成后沒(méi)有語(yǔ)法錯(cuò)誤崩溪,但無(wú)法知道系統(tǒng)的行為是否已經(jīng)被破壞。沒(méi)有對(duì)代碼進(jìn)行驗(yàn)證的CI不是真正的CI斩松。
當(dāng)構(gòu)建失敗后伶唯,我們是否把修復(fù)CI當(dāng)作第一優(yōu)先級(jí)的事情來(lái)做?
綠色的構(gòu)建意味著惧盹,我們的修改已經(jīng)安全地和已有代碼集成在一起乳幸。紅色的構(gòu)建意味著,最后一次修改很可能有問(wèn)題钧椰,這時(shí)只能提交修復(fù)構(gòu)建的代碼粹断。如果我們?cè)试S別人在構(gòu)建失敗時(shí)提交更多的修改,用于修復(fù)構(gòu)建的時(shí)間就會(huì)大大增加嫡霞。
將持續(xù)集成映射到微服務(wù)瓶埋,每個(gè)微服務(wù)都會(huì)有自己的代碼庫(kù)和構(gòu)建流程。
契約測(cè)試
契約測(cè)試最開(kāi)始的概念由Martin Fowler(ThoughtWorks首席科學(xué)家) 提出诊沪, 它又被稱之為消費(fèi)者驅(qū)動(dòng)的契約測(cè)試(CDC:Consumer Driven Contracts)养筒。這里的契約是指軟件系統(tǒng)中各個(gè)服務(wù)間交互的數(shù)據(jù)標(biāo)準(zhǔn)格式,更多的指消費(fèi)端(client)和提供端(server)之間交互的數(shù)據(jù)接口的格式端姚。
系統(tǒng)工程中存在這樣的理論:線性系統(tǒng)(即復(fù)雜性隨規(guī)模線性增長(zhǎng)的系統(tǒng))的可靠性等于組成它的各個(gè)組件的可靠性之乘積晕粪。這容易理解,因?yàn)檎麄€(gè)系統(tǒng)正常工作的條件是必須每個(gè)組件都同時(shí)正常工作渐裸。
如上圖表述的由三個(gè)組件共同支撐的系統(tǒng)巫湘。如果每個(gè)組件的可靠性是90%,那么整個(gè)系統(tǒng)的可靠性就是?90%×90%×90%=72.9%橄仆,我們可以看到系統(tǒng)整體的可靠度是低于任一組件的可靠性的剩膘。如果一個(gè)系統(tǒng)由100個(gè)組件組成,每個(gè)組件即使能達(dá)到99%的可靠性盆顾,那么整個(gè)系統(tǒng)的可靠性也會(huì)降到36.6%左右怠褐。
我們常說(shuō)復(fù)雜性是軟件工程的最重要的特性,一個(gè)完善的軟件系統(tǒng)必然是由很多的子系統(tǒng)您宪、組件共同撐起來(lái)的奈懒。隨著業(yè)務(wù)的復(fù)雜度越來(lái)越高奠涌,整個(gè)系統(tǒng)也變得越來(lái)越龐大和錯(cuò)綜復(fù)雜,在微服務(wù)的架構(gòu)下通常一個(gè)消費(fèi)端會(huì)與多個(gè)服務(wù)端相互交互磷杏,可以想象一下如果某一個(gè)服務(wù)的接口發(fā)生變化將會(huì)影響整個(gè)系統(tǒng)的運(yùn)行溜畅。
在微服務(wù)模式下如何保證各個(gè)服務(wù)端與消費(fèi)端之間以及服務(wù)與服務(wù)之間能夠可靠的交互呢?在服務(wù)端接口發(fā)生變化的情況下通過(guò)契約測(cè)試可以很容易的測(cè)試出契約不匹配极祸,在集成測(cè)試之前發(fā)現(xiàn)問(wèn)題慈格,盡早解決。(一般契約測(cè)試是在單元測(cè)試之后遥金,集成測(cè)試之前進(jìn)行的浴捆,首先在保證各自功能正確的前提下測(cè)試消費(fèi)者和提供者的契約是否相匹配,然后再進(jìn)一步的測(cè)試功能的完備性和整個(gè)業(yè)務(wù)流的正確性稿械。)
所以选泻,契約測(cè)試能解決這樣的問(wèn)題:
可以使得消費(fèi)端和提供端之間測(cè)試解耦,不再需要客戶端和服務(wù)端聯(lián)調(diào)才能發(fā)現(xiàn)問(wèn)題美莫。
完全由消費(fèi)者驅(qū)動(dòng)的方式页眯,消費(fèi)者需要什么數(shù)據(jù),服務(wù)端就提供什么樣的數(shù)據(jù)厢呵,數(shù)據(jù)契約也是由消費(fèi)者來(lái)決定的窝撵。
測(cè)試前移,越早的發(fā)現(xiàn)問(wèn)題述吸,保證后續(xù)測(cè)試的完整性忿族。
通過(guò)契約測(cè)試,團(tuán)隊(duì)能以一種離線的方式(不需要消費(fèi)者蝌矛、提供者同時(shí)在線)道批,通過(guò)契約作為中間的標(biāo)準(zhǔn),驗(yàn)證提供者提供的內(nèi)容是否滿足消費(fèi)者的期望入撒。
后記
去中心化與微服務(wù)——為了最大化微服務(wù)能帶來(lái)的自治性隆豹,我們需要持續(xù)尋找機(jī)會(huì),給擁有服務(wù)的團(tuán)隊(duì)委派決策和控制權(quán)茅逮。讓團(tuán)隊(duì)與組織保持一致璃赡,構(gòu)建面向業(yè)務(wù)服務(wù)的團(tuán)隊(duì),幫助團(tuán)隊(duì)的每個(gè)成員共同對(duì)系統(tǒng)技術(shù)愿景的演化負(fù)責(zé)献雅。
逐步開(kāi)始的重要性——在有能力大規(guī)模使用微服務(wù)之前碉考,請(qǐng)花費(fèi)一定的時(shí)間來(lái)構(gòu)建工具和實(shí)踐,幫助管理微服務(wù)挺身。這個(gè)過(guò)程可以幫助我們了解組織改變的意愿和能力侯谁,這將有助于正確地采用微服務(wù)。
本文作者萬(wàn)學(xué)凡,ThoughtWorks首席咨詢師墙贱,武漢热芹。作者保留本文一切權(quán)利,未經(jīng)許可請(qǐng)勿轉(zhuǎn)載惨撇。