原文是 Martin Flower 于 2014 年 3 月 25 日寫的《Microservices》匠璧。
微服務(wù)
“微服務(wù)架構(gòu)(Microservice Architecture)”一詞在過去幾年里廣泛的傳播寓娩,它用于描述一種設(shè)計(jì)應(yīng)用程序的特別方式脏毯,作為一套獨(dú)立可部署的服務(wù)胸梆。目前苫耸,這種架構(gòu)方式還沒有準(zhǔn)確的定義蜈块,但是在圍繞業(yè)務(wù)能力的組織曾沈、自動部署(automated deployment)、端智能(intelligence in the endpoints)烙博、語言和數(shù)據(jù)的分散控制瑟蜈,卻有著某種共同的特征烟逊。
“微服務(wù)(Microservices)”——只不過在滿大街充斥的軟件架構(gòu)中的一新名詞而已。盡管我們非常鄙視這樣的東西铺根,但是這玩意所描述的軟件風(fēng)格宪躯,越來越引起我們的注意。在過去幾年里位迂,我們發(fā)現(xiàn)越來越多的項(xiàng)目開始使用這種風(fēng)格访雪,以至于我們身邊的同事在構(gòu)建企業(yè)級應(yīng)用時(shí),把它理所當(dāng)然的認(rèn)為這是一種默認(rèn)開發(fā)形式掂林。然而臣缀,很不幸,微服務(wù)風(fēng)格是什么泻帮,應(yīng)該怎么開發(fā)精置,關(guān)于這樣的理論描述卻很難找到。
簡而言之锣杂,微服務(wù)架構(gòu)風(fēng)格脂倦,就像是把一個單獨(dú)的應(yīng)用程序開發(fā)為一套小服務(wù),每個小服務(wù)運(yùn)行在自己的進(jìn)程中元莫,并使用輕量級機(jī)制通信赖阻,通常是 HTTP API。這些服務(wù)圍繞業(yè)務(wù)能力來構(gòu)建踱蠢,并通過完全自動化部署機(jī)制來獨(dú)立部署政供。這些服務(wù)使用不同的編程語言書寫,以及不同數(shù)據(jù)存儲技術(shù)朽基,并保持最低限度的集中式管理。
在開始介紹微服務(wù)風(fēng)格(microservice style)前离陶,比較一下整體風(fēng)格(monolithic style)是很有幫助的:一個完整應(yīng)用程序(monolithic application)構(gòu)建成一個單獨(dú)的單元稼虎。企業(yè)級應(yīng)用通常被構(gòu)建成三個主要部分:客戶端用戶界面(由運(yùn)行在客戶機(jī)器上的瀏覽器的 HTML 頁面、Javascript 組成)招刨、數(shù)據(jù)庫(由許多的表構(gòu)成一個通用的霎俩、相互關(guān)聯(lián)的數(shù)據(jù)管理系統(tǒng))、服務(wù)端應(yīng)用沉眶。服務(wù)端應(yīng)用處理 HTTP 請求打却,執(zhí)行領(lǐng)域邏輯(domain logic),檢索并更新數(shù)據(jù)庫中的數(shù)據(jù)谎倔,使用適當(dāng)?shù)?HTML 視圖發(fā)送給瀏覽器柳击。服務(wù)端應(yīng)用是完整的 ,是一個單獨(dú)的的邏輯執(zhí)行片习。任何對系統(tǒng)的改變都涉及到重新構(gòu)建和部署一個新版本的服務(wù)端應(yīng)用程序捌肴。
這樣的整體服務(wù)(monolithic server)是一種構(gòu)建系統(tǒng)很自然的方式蹬叭。雖然你可以利用開發(fā)語基礎(chǔ)特性把應(yīng)用程序劃分成類、函數(shù)状知、命名空間秽五,但所有你處理請求的邏輯都運(yùn)行在一個單獨(dú)的進(jìn)程中。在某些場景中饥悴,開發(fā)者可以在的筆計(jì)本上開發(fā)坦喘、測試應(yīng)用,然后利用部署通道來保證經(jīng)過正常測試的變更西设,發(fā)布到產(chǎn)品中瓣铣。你也可以使用橫向擴(kuò)展,通過負(fù)載均衡將多個應(yīng)用部署到多臺服務(wù)器上济榨。
整體應(yīng)用程序(Monolithic applications)相當(dāng)成功坯沪,但是越來越多的人感覺到有點(diǎn)不妥,特別是在云中部署時(shí)擒滑。變更發(fā)布周期被綁定了——只是變更應(yīng)用程序的一小部分腐晾,卻要求整個重新構(gòu)建和部署。隨著時(shí)間的推移丐一,很難再保持一個好的模塊化結(jié)構(gòu)藻糖,使得一個模塊的變更很難不影響到其它模塊。擴(kuò)展就需要整個應(yīng)用程序的擴(kuò)展库车,而不能進(jìn)行部分?jǐn)U展巨柒。
這導(dǎo)致了微服務(wù)架構(gòu)風(fēng)格(microservice architectural style)的出現(xiàn):把應(yīng)用程序構(gòu)建為一套服務(wù)。事實(shí)是柠衍,服務(wù)可以獨(dú)立部署和擴(kuò)展洋满,每個服務(wù)提供了一個堅(jiān)實(shí)的模塊邊界,甚至不同的服務(wù)可以用不同的編程語言編寫珍坊。它們可以被不同的團(tuán)隊(duì)管理牺勾。
我們必須說,微服務(wù)風(fēng)格不是什么新東西阵漏,它至少可以追溯到 Unix 的設(shè)計(jì)原則驻民。但是并沒有太多人考慮微服務(wù)架構(gòu),如果他們用了履怯,那么很多軟件都會更好回还。
微服務(wù)風(fēng)格的特性
微服務(wù)風(fēng)格并沒有一個正式的定義,但我們可以嘗試描述一下微服務(wù)風(fēng)格所具有的共同特點(diǎn)叹洲。并不是所有的微服務(wù)風(fēng)格都要具有所有的特性柠硕,但我們期望常見的微服務(wù)都應(yīng)該有這些特性。我們的意圖是嘗試描述我們工作中或者在其它我們了解的組件中所理解的微服務(wù)运提。特別是仅叫,我們不依賴于那些已經(jīng)明確過的定義帜篇。
組件化(Componentization )與服務(wù)(Services)
自從我們開始軟件行業(yè)以來,一直希望由組件構(gòu)建系統(tǒng)诫咱,就像我們在物理世界所看到的一樣笙隙。在過去的幾十年里,我們已經(jīng)看到了公共庫的大量簡編取得了相當(dāng)?shù)倪M(jìn)步坎缭,這些庫是大部分語言平臺的一部分竟痰。
當(dāng)我們談?wù)摻M件時(shí),可能會陷入一個困境——什么是組件掏呼。我們的定義是坏快,組件(component)是一個可獨(dú)立替換和升級的軟件單元。
微服務(wù)架構(gòu)(Microservice architectures)會使用庫(libraries)憎夷,但組件化軟件的主要方式是把它拆分成服務(wù)莽鸿。我們把庫(libraries)定義為組件,這些組件被鏈接到程序拾给,并通過內(nèi)存中函數(shù)調(diào)用(in-memory function calls)來調(diào)用祥得,而服務(wù)(services )是進(jìn)程外組件(out-of-process components),他們利用某個機(jī)制通信蒋得,比如 WebService 請求级及,或遠(yuǎn)程過程調(diào)用(remote procedure call)。組件和服務(wù)在很多面向?qū)ο缶幊讨惺遣煌母拍睢?/p>
把服務(wù)當(dāng)成組件(而不是組件庫)的一個主要原因是额衙,服務(wù)可以獨(dú)立部署饮焦。如果你的應(yīng)用程序是由一個單獨(dú)進(jìn)程中的很多庫組成,那么對任何一個組件的改變都將導(dǎo)致必須重新部署整個應(yīng)用程序窍侧。但是如果你把應(yīng)用程序拆分成很多服務(wù)县踢,那你只需要重新部署那個改變的服務(wù)。當(dāng)然伟件,這也不是絕對的殿雪,有些服務(wù)會改變導(dǎo)致協(xié)調(diào)的服務(wù)接口,但是一個好的微服務(wù)架構(gòu)的目標(biāo)就是通過在服務(wù)契約(service contracts)中解耦服務(wù)的邊界和進(jìn)化機(jī)制來避免這些锋爪。
另一個考慮是,把服務(wù)當(dāng)組件將擁有更清晰的組件接口爸业。大多數(shù)開發(fā)語言都沒有一個良好的機(jī)制來定義一個發(fā)布的接口(Published Interface)其骄。發(fā)布的接口是指一個類向外公開的成員,比如 Java 中的聲明為 Public 的成員扯旷,C# 中聲明為非 Internal 的成員拯爽。通常只有在文檔和規(guī)范中會說明,這是為了讓避免客戶端破壞組件的封裝性钧忽,阻止組件間緊耦合毯炮。服務(wù)通過使用公開遠(yuǎn)程調(diào)用機(jī)制可以很容易避免這些逼肯。
像這樣使用服務(wù)也有不足之處。遠(yuǎn)程調(diào)用比進(jìn)制內(nèi)調(diào)用更消耗資源桃煎,因此遠(yuǎn)程 API 需要粗粒度(coarser-grained)篮幢,但這會比較難使用。如果你需要調(diào)整組件間的職責(zé)分配为迈,當(dāng)跨越進(jìn)程邊界時(shí)三椿,這樣做將會很難。
一個可能是葫辐,我們看到搜锰,服務(wù)可以映射到運(yùn)行時(shí)進(jìn)程(runtime processes)上,但也只是一個可能耿战。服務(wù)可以由多個進(jìn)程組成蛋叼,它們會同時(shí)開發(fā)和部署,例如一個應(yīng)用程序進(jìn)程和一個只能由這個服務(wù)使用的數(shù)據(jù)庫剂陡。
圍繞業(yè)務(wù)功能的組織
當(dāng)尋找把一個大的應(yīng)用程序拆分成小的部分時(shí)狈涮,通常管理都會集中在技術(shù)層面,UI團(tuán)隊(duì)鹏倘、服務(wù)端業(yè)務(wù)邏輯團(tuán)隊(duì)和數(shù)據(jù)庫團(tuán)隊(duì)薯嗤。當(dāng)使用這種標(biāo)準(zhǔn)對團(tuán)隊(duì)進(jìn)行劃分時(shí),甚至小小的更變都將導(dǎo)致跨團(tuán)隊(duì)項(xiàng)目協(xié)作纤泵,從而消耗時(shí)間和預(yù)算審批骆姐。一個高效的團(tuán)隊(duì)會針對這種情況進(jìn)行改善,兩權(quán)相害取其輕捏题。業(yè)務(wù)邏輯無處不在玻褪。實(shí)踐中,這就是 Conway’s Law 的一個例子公荧。
設(shè)計(jì)一個系統(tǒng)的任何組織(廣義上)都會產(chǎn)生這樣一種設(shè)計(jì)带射,其結(jié)構(gòu)是組織交流結(jié)構(gòu)的復(fù)制。
——Melvyn Conway, 1967
Melvyn Conway 的意思是循狰,像下圖所展示的窟社,設(shè)計(jì)一個系統(tǒng)時(shí),將人員劃分為 UI 團(tuán)隊(duì)绪钥,中間件團(tuán)隊(duì)灿里,DBA 團(tuán)隊(duì),那么相應(yīng)地程腹,軟件系統(tǒng)也就會自然地被劃分為 UI 界面匣吊,中間件系統(tǒng),數(shù)據(jù)庫。
微服務(wù)(microservice )的劃分方法不同色鸳,它傾向圍繞業(yè)務(wù)功能的組織來分割服務(wù)社痛。這些服務(wù)實(shí)現(xiàn)商業(yè)領(lǐng)域的軟件,包括用戶界面命雀,持久化存儲蒜哀,任何的外部協(xié)作。因此咏雌,團(tuán)隊(duì)是跨職能的(cross-functional)凡怎,包含開發(fā)過程所要求的所有技能:用戶體驗(yàn)(user-experience)、數(shù)據(jù)庫(database)和項(xiàng)目管理(project management)赊抖。
www.comparethemarket.com就是采用這種組織形式统倒。跨職能的團(tuán)隊(duì)同時(shí)負(fù)責(zé)構(gòu)建和運(yùn)營每個產(chǎn)品氛雪,每個產(chǎn)品被分割成許多單個的服務(wù)房匆,這些服務(wù)通過消息總線(Message Bus)通信。
大型的整體應(yīng)用程序(monolithic applications)也可以按照業(yè)務(wù)功能進(jìn)行模塊化(modularized)报亩,盡管這樣情況不常見浴鸿。當(dāng)然,我們可以敦促一個構(gòu)建整體應(yīng)用程序(monolithic application )的大型團(tuán)隊(duì)弦追,按業(yè)務(wù)線來分割自己岳链。我們已經(jīng)看到的主要問題是,這種組件形式會導(dǎo)致很多的依賴劲件。如果整體應(yīng)用程序(monolithic applications)跨越很多模塊邊界(modular boundaries )掸哑,那么對于團(tuán)隊(duì)的每個成員短期內(nèi)修復(fù)它們是很困難的。此外零远,我們發(fā)現(xiàn)苗分,模塊化需要大量的強(qiáng)制規(guī)范。服務(wù)組件所要求的必需的更明確的分離使得保持團(tuán)隊(duì)邊界清晰更加容易牵辣。
產(chǎn)品不是項(xiàng)目
大部分的軟件開發(fā)者都使用這樣的項(xiàng)目模式:至力于提供一些被認(rèn)為是完整的軟件摔癣。交付一個他們認(rèn)為完成的軟件。軟件移交給運(yùn)維組織纬向,然后择浊,解散構(gòu)建軟件的團(tuán)隊(duì)。
微服務(wù)(Microservice )的支持者認(rèn)為這種做法是不可取的逾条,并提議團(tuán)隊(duì)?wèi)?yīng)該負(fù)責(zé)產(chǎn)品的整個生命周期琢岩。Amazon 理念是“你構(gòu)建,你運(yùn)維(you build, you run it)”膳帕,要求開發(fā)團(tuán)隊(duì)對軟件產(chǎn)品的整個生命周期負(fù)責(zé)。這要求開發(fā)者每天都關(guān)注他們的軟件運(yùn)行如何,增加更用戶的聯(lián)系危彩,同時(shí)承擔(dān)一些售后支持攒磨。
產(chǎn)品的理念,跟業(yè)務(wù)能力聯(lián)系起來汤徽。不是著眼于完成一套功能的軟件娩缰,而是有一個持續(xù)的關(guān)系,是如何能夠幫助軟件及其用戶提升業(yè)務(wù)能力谒府。
為什么相同的方法不能用在整體應(yīng)用程序(monolithic applications)拼坎,但更小的服務(wù)粒度能夠使創(chuàng)建服務(wù)的開發(fā)者與使用者之間的個人聯(lián)系更容易。
強(qiáng)化終端及弱化通道
當(dāng)構(gòu)建不同的進(jìn)程間通信機(jī)制的時(shí)候完疫,我們發(fā)現(xiàn)有許多的產(chǎn)品和方法能夠把更加有效方法強(qiáng)加入的通信機(jī)制中泰鸡。比如企業(yè)服務(wù)總線(ESB),這樣的產(chǎn)品提供更有效的方式改進(jìn)通信過程中的路由壳鹤、編碼盛龄、傳輸、以及業(yè)務(wù)處理規(guī)則芳誓。
微服務(wù)傾向于做如下的選擇:強(qiáng)化終端及弱化通道余舶。微服務(wù)的應(yīng)用致力松耦合和高內(nèi)聚:采用單獨(dú)的業(yè)務(wù)邏輯,表現(xiàn)的更像經(jīng)典Unix意義上的過濾器一樣锹淌,接受請求匿值、處理業(yè)務(wù)邏輯、返回響應(yīng)赂摆。它們更喜歡簡單的REST風(fēng)格挟憔,而不是復(fù)雜的協(xié)議,如WS或者BPEL或者集中式框架库正。
有兩種協(xié)議最經(jīng)常被使用到:包含資源API的HTTP的請求-響應(yīng)和輕量級消息通信協(xié)議曲楚。最為重要的建議為:
善于利用網(wǎng)絡(luò),而不是限制(Be of the web, not behind the web)褥符。
——Ian Robinson
微服務(wù)團(tuán)隊(duì)采用這樣的原則和規(guī)范:基于互聯(lián)網(wǎng)(廣義上龙誊,包含Unix系統(tǒng))構(gòu)建系統(tǒng)。這樣經(jīng)常使用的資源幾乎不用什么的代價(jià)就可以被開發(fā)者或者運(yùn)行商緩存喷楣。
第二種做法是通過輕量級消息總線來發(fā)布消息趟大。這種的通信協(xié)議非常的單一(單一到只負(fù)責(zé)消息路由),像RabbitMQ或者ZeroMQ這樣的簡單的實(shí)現(xiàn)甚至像可靠的異步機(jī)制都沒提供铣焊,以至于需要依賴產(chǎn)生或者消費(fèi)消息的終端或者服務(wù)來處理這類問題逊朽。
在整體工風(fēng)格中,組件在進(jìn)程內(nèi)執(zhí)行曲伊,進(jìn)程間的消息通信通常通過調(diào)用方法或者回調(diào)函數(shù)叽讳。從整體式風(fēng)格到微服務(wù)框架最大的問題在于通信方式的變更追他。從內(nèi)存內(nèi)部原始的調(diào)用變成遠(yuǎn)程調(diào)用,產(chǎn)生的大量的不可靠通信岛蚤。因此邑狸,你需要把粗粒度的方法成更加細(xì)粒度的通信。
分散治理
集中治理的一種好處是在單一平臺上進(jìn)行標(biāo)準(zhǔn)化涤妒。經(jīng)驗(yàn)表明這種趨勢的好處在縮小单雾,因?yàn)椴⒉皇撬械膯栴}都相同,而且解決方案并不是萬能的她紫。我們更加傾向于采用適當(dāng)?shù)墓ぞ呓鉀Q適當(dāng)?shù)膯栴}硅堆,整體式的應(yīng)用在一定程度上比多語言環(huán)境更有優(yōu)勢,但也適合所有的情況贿讹。
把整體式框架中的組件渐逃,拆分成不同的服務(wù),我們在構(gòu)建它們時(shí)有更多的選擇围详。你想用Node.js去開發(fā)報(bào)表頁面嗎朴乖?做吧。用C++來構(gòu)建時(shí)時(shí)性要求高的組件助赞?很好买羞。你想以在不同類型的數(shù)據(jù)庫中切換,來提高組件的讀取性能雹食?我們現(xiàn)在有技術(shù)手段來實(shí)現(xiàn)它了畜普。
當(dāng)然,你是可以做更多的選擇群叶,但也不意味的你就可以這樣做吃挑,因?yàn)槟愕南到y(tǒng)使用這種方式進(jìn)行侵害意味著你已經(jīng)有的決定。
采用微服務(wù)的團(tuán)隊(duì)更喜歡不同的標(biāo)準(zhǔn)街立。他們不會把這些標(biāo)準(zhǔn)寫在紙上舶衬,而是喜歡這樣的思想:開發(fā)有用的工具來解決開發(fā)者遇到的相似的問題。這些工具通常從實(shí)現(xiàn)中成長起來赎离,并進(jìn)行的廣泛范圍內(nèi)分享逛犹,當(dāng)然,它們有時(shí)梁剔,并不一定虽画,會采用開源模式。現(xiàn)在開源的做法也變得越來越普遍荣病,git或者github成為了它們事實(shí)上的版本控制系統(tǒng)码撰。
Netfix就是這樣的一個組織,它是非常好的一個例子个盆。分享有用的脖岛、尤其是經(jīng)過實(shí)踐的代碼庫激勵著其它的開發(fā)著也使用相似的方式來解決相似的問題朵栖,當(dāng)然,也保留著根據(jù)需要使用不同的方法的權(quán)力柴梆。共享庫更關(guān)注于數(shù)據(jù)存儲混槐、進(jìn)程內(nèi)通信以及我們接下來做討論到的自動化等這些問題上。
微服務(wù)社區(qū)中轩性,開銷問題特別引人注意。這并不是說狠鸳,社區(qū)不認(rèn)為服務(wù)交互的價(jià)值揣苏。相反,正是因?yàn)榘l(fā)現(xiàn)到它的價(jià)值件舵。這使得他們在尋找各種方法來解決它們卸察。如Tolearant Reader和Consumer-Driven Contracts這樣的設(shè)計(jì)模式就經(jīng)常被微服務(wù)使用。這些模式解決了獨(dú)立服務(wù)在交互過程中的消耗問題铅祸。使用Consumer-Driven Contracts增加了你的信心坑质,并實(shí)現(xiàn)了快速的反饋機(jī)制。事實(shí)上临梗,我們知道澳大利亞的一個團(tuán)隊(duì)致力使用Consumer-Drvien Contracts開發(fā)新的服務(wù)涡扼。他們使用簡單的工程,幫助他們定義服務(wù)的接口盟庞。使得在新服務(wù)的代碼開始編寫之前吃沪,這些接口就成為自動化構(gòu)建的一個部分。構(gòu)建出來的服務(wù)什猖,只需要指出這些接口適用的范圍票彪,一個優(yōu)雅的方法避免了新軟件中的’YAGNI ‘困境。這些技術(shù)和工具在使用過程中完善不狮,通過減少服務(wù)間的耦合降铸,限制了集中式管理的需求。
也許分散治理普及于亞馬遜“編譯它摇零,運(yùn)維它”的理念推掸。團(tuán)隊(duì)為他們開發(fā)的軟件負(fù)全部責(zé)任,也包含7*24小時(shí)的運(yùn)行遂黍。全責(zé)任的方式并不常見终佛,但是我們確實(shí)發(fā)現(xiàn)越來越多的公司在他們的團(tuán)隊(duì)中所推廣。Netfix是另外一個接受這種理念的組件雾家。每天凌晨3點(diǎn)被鬧鐘吵醒铃彰,因?yàn)槟惴浅5年P(guān)注寫的代碼質(zhì)量。這在傳統(tǒng)的集中式治理中這是一樣多么不思議的事情呀芯咧。
分散數(shù)據(jù)管理
對數(shù)據(jù)的分散管理有多種不同的表現(xiàn)形式牙捉。最為抽象層次竹揍,它意味著不同系統(tǒng)中的通用概念是不同的。這帶來的覺問題是大型的跨系統(tǒng)整合時(shí)邪铲,用戶使用不同的售后支持將得到不同的促銷信息芬位。這種情況叫做并沒有給用戶顯示所有的促銷手段。不同的語法確實(shí)存在相同的詞義或者(更差)相同的詞義带到。
應(yīng)用之間這個問題很普遍昧碉,但應(yīng)用內(nèi)部這個問題也存在,特別是當(dāng)應(yīng)用拆分成不同的組件時(shí)揽惹。對待這個問題非常有用的方式為Bounded Context的領(lǐng)域驅(qū)動設(shè)計(jì)被饿。DDD把復(fù)雜的領(lǐng)域拆分成不同上下文邊界以及它們之間的關(guān)系。這樣的過程對于整體架構(gòu)和微服務(wù)框架都很有用搪搏,但是服務(wù)間存在著明顯的關(guān)系狭握,幫助我們對上下文邊界進(jìn)行區(qū)分,同時(shí)也像我們在業(yè)務(wù)功能中談到的疯溺,強(qiáng)行拆分论颅。
當(dāng)對概念模式下決心進(jìn)行分散管理時(shí),微服務(wù)也決定著分散數(shù)據(jù)管理囱嫩。當(dāng)整體式的應(yīng)用使用單一邏輯數(shù)據(jù)庫對數(shù)據(jù)持久化時(shí)恃疯,企業(yè)通常選擇在應(yīng)用的范圍內(nèi)使用一個數(shù)據(jù)庫,這些決定也受廠商的商業(yè)權(quán)限模式驅(qū)動墨闲。微服務(wù)讓每個服務(wù)管理自己的數(shù)據(jù)庫:無論是相同數(shù)據(jù)庫的不同實(shí)例澡谭,或者是不同的數(shù)據(jù)庫系統(tǒng)。這種方法叫Polyglot Persistence损俭。你可以把這種方法用在整體架構(gòu)中蛙奖,但是它更常見于微服務(wù)架構(gòu)中。
微服務(wù)音分散數(shù)據(jù)現(xiàn)任意味著管理數(shù)據(jù)更新杆兵。處理數(shù)據(jù)更新的常用方法是使用事務(wù)來保證不同的資源修改數(shù)據(jù)庫的一致性雁仲。這種方法通常在整體架構(gòu)中使用。
使用事務(wù)是因?yàn)樗軌驇椭幚硪恢列詥栴}琐脏,但對時(shí)間的消耗是嚴(yán)重的攒砖,這給跨服務(wù)操作帶來難題。分布式事務(wù)非常難以實(shí)施日裙,因此微服務(wù)架構(gòu)強(qiáng)調(diào)服務(wù)間事務(wù)的協(xié)調(diào)吹艇,并清楚的認(rèn)識一致性只能是最終一致性以及通過補(bǔ)償運(yùn)算處理問題。
選擇處理不一致問題對于開發(fā)團(tuán)隊(duì)來說是新的挑戰(zhàn)昂拂,但是也是一個常見的業(yè)務(wù)實(shí)踐模式受神。通常業(yè)務(wù)上允許一定的不一致以滿足快速響應(yīng)的需求,但同時(shí)也采用一些恢復(fù)的進(jìn)程來處理這種錯誤格侯。當(dāng)業(yè)務(wù)上處理強(qiáng)一致性消耗比處理錯誤的消耗少時(shí)鼻听,這種付出是值的的财著。
基礎(chǔ)設(shè)施自動化
基礎(chǔ)設(shè)施自動化技術(shù)在過去幾年中得到了長足的發(fā)展:云計(jì)算,特別是AWS的發(fā)展撑碴,減少了構(gòu)建撑教、發(fā)布、運(yùn)維微服務(wù)的復(fù)雜性醉拓。
許多使用微服務(wù)架構(gòu)的產(chǎn)品或者系統(tǒng)伟姐,它們的團(tuán)隊(duì)擁有豐富的持集部署以及它的前任持續(xù)集成的經(jīng)驗(yàn)卓囚。團(tuán)隊(duì)使用這種方式構(gòu)建軟件致使更廣泛的依賴基礎(chǔ)設(shè)施自動化技術(shù)付魔。下圖說明這種構(gòu)建的流程:
盡管這不是介紹自動部署的文章,但我們也打算介紹一下它的主要特征箩溃。我們希望我們的軟件應(yīng)該這樣方便的工作怠噪,因此我們需要更多的自動化測試。流程中工作的軟件改進(jìn)意味著我們能自動的部署到各種新的環(huán)境中杜跷。
整體風(fēng)格的應(yīng)用相當(dāng)開心的在各種環(huán)境中構(gòu)建傍念、測試、發(fā)布葛闷。事實(shí)證明憋槐,一旦你打算投資一條整體架構(gòu)應(yīng)用自動化的的生產(chǎn)線,那么你會發(fā)現(xiàn)發(fā)布更多的應(yīng)用似乎非不那么的可怕淑趾。記住阳仔,CD(持續(xù)部署)的一個目標(biāo)在于讓發(fā)布變得無趣,因此無論是一個還是三個應(yīng)用扣泊,它都一樣的無趣近范。
另一個方面,我們發(fā)現(xiàn)使用微服務(wù)的團(tuán)隊(duì)更加依賴于基礎(chǔ)設(shè)施的自動化延蟹。相比之下评矩,在整體架構(gòu)也微服務(wù)架構(gòu)中,盡管發(fā)布的場景不同阱飘,但發(fā)布工作的無趣并沒有多大的區(qū)別斥杜。
容錯性設(shè)計(jì)
使用服務(wù)作為組件的一個結(jié)果在于應(yīng)用需要有能容忍服務(wù)的故障的設(shè)計(jì)。任務(wù)服務(wù)可能因?yàn)楣?yīng)商的不可靠而故障沥匈,客戶端需要盡可能的優(yōu)化這種場景的響應(yīng)蔗喂。跟整體構(gòu)架相比,這是一個缺點(diǎn)高帖,因?yàn)樗鼛淼念~外的復(fù)雜性缰儿。這將讓微服務(wù)團(tuán)隊(duì)時(shí)刻的想到服務(wù)故障的情況下用戶的體驗(yàn)。Netflix 的Simian Army可以為每個應(yīng)用的服務(wù)及數(shù)據(jù)中心提供日常故障檢測和恢復(fù)散址。
這種產(chǎn)品中的自動化測試可以讓大部分的運(yùn)維團(tuán)隊(duì)正常的上下班返弹。這并不意味著整體構(gòu)架的應(yīng)用沒有這么精巧的監(jiān)控配置锈玉,只是在我們的經(jīng)驗(yàn)中它并不常見。
由于服務(wù)可以隨時(shí)故障义起,快速故障檢測拉背,乃至,自動恢復(fù)變更非常重要默终。微服務(wù)應(yīng)用把實(shí)時(shí)的監(jiān)控放在應(yīng)用的各個階段中椅棺,檢測構(gòu)架元素(每秒數(shù)據(jù)庫的接收的請求數(shù))和業(yè)務(wù)相關(guān)的指標(biāo)(把分鐘接收的定單數(shù))。監(jiān)控系統(tǒng)可以提供一種早期故障告警系統(tǒng)齐蔽,讓開發(fā)團(tuán)隊(duì)跟進(jìn)并調(diào)查两疚。
對于微服務(wù)框架來說,這相當(dāng)重要含滴,因?yàn)槲⒎?wù)相互的通信可能導(dǎo)致緊急意外行為诱渤。許多專家車稱贊這種緊急事件的價(jià)值,但事實(shí)是這種緊急行為有時(shí)是災(zāi)難谈况。監(jiān)控是至關(guān)重要的勺美,它能快速發(fā)現(xiàn)這種緊急不良行為,讓我們迅速修復(fù)它碑韵。
整體架構(gòu)赡茸,跟微服務(wù)一樣,在構(gòu)建時(shí)是通明的祝闻,實(shí)情上占卧,它們就是這樣子的。它們不同之處在于联喘,你需要清楚的認(rèn)識到不同進(jìn)程間運(yùn)行的服務(wù)是不相關(guān)的华蜒。庫對于同一進(jìn)程是透明的,也因此不那么重要了豁遭。
微服務(wù)團(tuán)隊(duì)期望清楚的監(jiān)控和記錄每個服務(wù)的配置友多,比如使用儀表盤顯示上/下線狀態(tài)、各種運(yùn)維和業(yè)務(wù)相關(guān)的指標(biāo)堤框。對斷路器(circuit breaker)狀態(tài)域滥、目前的吞吐量和時(shí)延細(xì)節(jié),我們也會經(jīng)常遇到蜈抓。
設(shè)計(jì)改進(jìn)
微服務(wù)實(shí)踐者启绰,通常有不斷改進(jìn)設(shè)計(jì)的背景,他們把服務(wù)分解成進(jìn)一步的工具沟使。這些工具可以讓應(yīng)用開發(fā)者在不改變速度情況下委可,控制都他們的應(yīng)用的需求變更。變更控制不意味首減少變更,而是使用適當(dāng)?shù)姆绞胶凸ぞ咦徘悖屗宇l繁拾酝,至少,很好讓它變得可控卡者。
不論如何蒿囤,當(dāng)你試圖軟件系統(tǒng)拆分成組件時(shí),你將面臨著如何拆分的問題崇决。那么我們的決定拆分我們應(yīng)用的原則是什么呢材诽?首要的因素,組件可以被獨(dú)立替換和更新的恒傻,這意味著我們尋找的關(guān)鍵在于脸侥,我們要想象著重寫一個組件而不影響它們之前的協(xié)作關(guān)系。事實(shí)上盈厘,許多的微服務(wù)小組給它進(jìn)一步的預(yù)期:服務(wù)應(yīng)該能夠報(bào)廢的睁枕,而不是要長久的發(fā)展的。
Guardian網(wǎng)站就是這方面的一個優(yōu)秀的例子沸手,它初期被設(shè)計(jì)和構(gòu)建成一個整體架構(gòu)外遇,但它已經(jīng)向微服務(wù)的發(fā)展了。整體構(gòu)架仍然是它網(wǎng)站的核心罐氨,但是他們使用微服務(wù)來增加那些使用整體架構(gòu)API的新特性。這種方法增加這些臨時(shí)的特性非常方便滩援,比如運(yùn)動新聞的特稿栅隐。這樣站點(diǎn)的一個部分可以使用快速的開發(fā)語言迅速整合起來,當(dāng)它過時(shí)后可以一次性移除玩徊。我們發(fā)現(xiàn)一家金融機(jī)構(gòu)用相似的方法增加新的市場營銷活動租悄,數(shù)周或者幾個月后把它撤銷。
可代替是模塊化開發(fā)中的一個特例恩袱,它是用模塊來應(yīng)對需要變更的泣棋。你希望讓變更是相同模塊,相同周期中進(jìn)行變化而已畔塔。系統(tǒng)的某些很小做變更部分潭辈,也應(yīng)該放在不同的服務(wù)中,這樣它們更容易讓它們消亡澈吨。如果你發(fā)現(xiàn)兩個服務(wù)一直重復(fù)的變更時(shí)把敢,這就是一個要合并它們的信號了。
把組件改成服務(wù)谅辣,增加了細(xì)化發(fā)布計(jì)劃的一個機(jī)會修赞。整體構(gòu)架的任務(wù)變更需要整個應(yīng)用的完整的構(gòu)建和發(fā)布。然而桑阶,使用微服務(wù)柏副,你只需要發(fā)布你要修改的服務(wù)就可以了勾邦。這將簡化和加速你的發(fā)布周期。缺點(diǎn)是你需要為一個變更服務(wù)發(fā)布可能中斷用戶的體驗(yàn)而擔(dān)心割择。傳統(tǒng)的集成方法是使用版本來處理這些問題眷篇,但是微服務(wù)版本僅是最后的通告手段。我們需要在設(shè)計(jì)服務(wù)時(shí)盡可能的容忍供應(yīng)商的變更锨推,以避免提供多個版本铅歼。
微服務(wù)是未來嗎?
我們寫這篇文章的主要目的在于解釋微服務(wù)的主要思想和原則换可。但是發(fā)時(shí)間做這事的時(shí)候椎椰,我們清醒的認(rèn)識到微服務(wù)構(gòu)架風(fēng)格是一個非常重要的想法:一個值得企業(yè)應(yīng)用中認(rèn)真考慮的東西。我們最近使用這種風(fēng)格構(gòu)建了幾個系統(tǒng)沾鳄,認(rèn)識那些也使用和喜歡這種方法的愛好者慨飘。
我們認(rèn)識的使用這種方式的先行者,包含亞馬遜译荞、Netflix瓤的、The Guardian、The UK Government Digital Service吞歼、realestate.com.au圈膏、Forward和comparethemarket.com。2013看的巡回會議充滿了向正在想成為微服務(wù)一分子的公司篙骡,包含Travis CI稽坤。此外,大量的組件正在從事我們認(rèn)為是微服務(wù)的事糯俗,只是沒有使用微服務(wù)的名字而已尿褪。(通常,它們被打上SOA的標(biāo)簽得湘,盡管杖玲,我們認(rèn)為SOA有許多不同的地方。)
盡管有這些積極的經(jīng)驗(yàn)淘正,然后摆马,我們也不急于確認(rèn)微服務(wù)是未來軟件架構(gòu)方向。至今為止鸿吆,我們的經(jīng)驗(yàn)與整體風(fēng)格的應(yīng)該中相比出來的是有優(yōu)勢的今膊,但是我們意識知這樣的事實(shí),我們并沒有足夠的時(shí)間來證明我們的論證伞剑。
你所使用的架構(gòu)通常是你開發(fā)出來后斑唬,使用的幾年的實(shí)際成果。我們看到這些工程是在一個優(yōu)秀的團(tuán)隊(duì),帶著對模塊化的強(qiáng)烈追求恕刘,使用在過去幾年中已經(jīng)衰退的整體架構(gòu)構(gòu)建出來的缤谎。許多人相信,這種衰退不太可能與微服務(wù)有關(guān)褐着,因?yàn)榉?wù)邊界是清晰的并且很難再完善的坷澡。然而,當(dāng)我們還沒看到足夠多的系統(tǒng)運(yùn)行足夠長時(shí)間時(shí)含蓉,我們不能肯定微服務(wù)構(gòu)架是成熟的频敛。
當(dāng)然,還有原因就是馅扣,有人期望微服務(wù)構(gòu)架不夠成熟斟赚。在組件化方面的任何努力,其成功都依賴于軟件如何拆分成適合的組件差油。指出組件化的準(zhǔn)確邊界應(yīng)該在那拗军,這是非常困難的。改良設(shè)計(jì)要承認(rèn)邊界的權(quán)益困境和因此帶來的易于重構(gòu)的重要性蓄喇。但是當(dāng)你的組件是被遠(yuǎn)程通信的服務(wù)時(shí)发侵,重構(gòu)比進(jìn)程內(nèi)的庫又要困難的多。服務(wù)邊界上的代碼遷移是困難的妆偏,任務(wù)接口的變更需要參與者的共同協(xié)作刃鳄,向后兼容的層次需要被增加,測試也變更更加復(fù)雜钱骂。
另一個問題在于叔锐,如果組件并沒有清晰的劃分,你的工作的復(fù)雜性將從組件內(nèi)部轉(zhuǎn)向組件間的關(guān)系罐柳。做這事不僅要圍繞著復(fù)雜掌腰,它也要面對著不清晰和更難控制的地方狰住。很容易想到张吉,當(dāng)你在一個小的、簡單的組件內(nèi)找東西催植,總比在沒有關(guān)系的混亂的服務(wù)間要容易肮蛹。
最后,團(tuán)隊(duì)技能也是重要的因素创南。新的技術(shù)傾向于被掌握更多的技能的團(tuán)隊(duì)使用伦忠。但是掌握多技能的團(tuán)隊(duì)中使用的技巧在較少技能的團(tuán)隊(duì)中并不是必需的。我們發(fā)現(xiàn)大量的少技能的團(tuán)隊(duì)構(gòu)建混亂的整合構(gòu)架稿辙,但是它要發(fā)時(shí)間去證明使用微服務(wù)在這種情況下會發(fā)生什么昆码。一個糟糕的團(tuán)隊(duì)通常開發(fā)糟糕的系統(tǒng):很難說,微服務(wù)在這種情況下是否能幫助它們,還是破壞它們赋咽。
一個理性的爭議在于旧噪,我們聽說,你不應(yīng)該從微服務(wù)構(gòu)架開始做脓匿。最好從整體構(gòu)架開發(fā)淘钟,做模塊化開發(fā),然后當(dāng)整體構(gòu)架出現(xiàn)問題是再把模塊化拆分成服務(wù)陪毡。(盡管這種建議不是好主意米母,因?yàn)橐粋€好的進(jìn)程內(nèi)接口并不是一個好的服務(wù)接口。)
因此我們持這種謹(jǐn)慎的樂觀毡琉。到目前為止铁瞒,我們還沒有足夠認(rèn)識,關(guān)于微構(gòu)架能否被大范圍的推廣绊起。我們不能肯定的說精拟,我們要終結(jié)什么,但是軟件開發(fā)的挑戰(zhàn)在于你只能在不完整的信息中決定你目前要處理的問題虱歪。
其它
微服務(wù)系統(tǒng)多大蜂绎?
盡管“微服務(wù)”一詞在架構(gòu)風(fēng)格中越來越流行,它的名字很不辛讓人關(guān)注它的服務(wù)大小笋鄙,以及對“微”這個組成的爭議师枣。在我們與微服務(wù)實(shí)踐者的談話中,我們發(fā)現(xiàn)了服務(wù)的大小范圍萧落。被報(bào)道的最大團(tuán)隊(duì)遵循亞馬遜Tow Pizaa團(tuán)隊(duì)理念(比如践美,一個團(tuán)隊(duì)吃兩個比薩就可以了。)找岖,這意味著不超過20號(一打)人陨倡。我們發(fā)現(xiàn)最小配置是半打的團(tuán)隊(duì)支撐起一打的服務(wù)。
這也引發(fā)這樣的考慮:規(guī)模為一個服務(wù)一打人到一個服務(wù)一個人的團(tuán)隊(duì)打上微服務(wù)的標(biāo)簽许布。此刻我們認(rèn)為兴革,它們是一樣的,但是隨著對這種風(fēng)格的深入研究蜜唾,也存在我們改變我們的想法的可能杂曲。
微服務(wù)與SOA
當(dāng)前我們談到微服務(wù)時(shí),通常會問袁余,這是不是我們20年前討論的面向服務(wù)架構(gòu)(SOA)擎勘。這是一個很好的觀點(diǎn),因?yàn)槲⒎?wù)風(fēng)格也SOA所提倡的一些優(yōu)勢非常相似颖榜。盡管如此棚饵,問題在于SOA意味的太多不同的東西了煤裙,因此通常時(shí)候我們談的所謂“SOA”時(shí),它與我們談?wù)摰娘L(fēng)格不一至噪漾,因?yàn)樗ǔJ侵冈谡w風(fēng)格應(yīng)用中的ESB积暖。
此外,我們發(fā)現(xiàn)面向服務(wù)的風(fēng)格是這么的拙劣:從試圖使用ESB隱藏復(fù)雜性怪与, 到使用多年才認(rèn)識到發(fā)費(fèi)數(shù)百美元卻沒產(chǎn)生任務(wù)價(jià)值這樣的失敗夺刑,到集中治理模式抑制變更。而且這些問題往往很難發(fā)現(xiàn)分别。
可以肯定的時(shí)遍愿,微服務(wù)社區(qū)中使用的許多的技術(shù)都開發(fā)者是從大型機(jī)構(gòu)的整合服務(wù)經(jīng)驗(yàn)中發(fā)展來的。Tolerant Reader模式就是這樣的一個例子耘斩。由于互聯(lián)網(wǎng)的發(fā)展沼填,利用簡單的協(xié)議這種方法,讓它從這些經(jīng)驗(yàn)傳達(dá)的出來括授。這是從已經(jīng)很復(fù)雜的集中式標(biāo)準(zhǔn)中的一種反模式坞笙,坦白的說,真讓人驚嘆荚虚。(無論何時(shí)薛夜,當(dāng)你需要用一個服務(wù)來管理你的所有的服務(wù),你就知道這很麻煩版述。)
SOA的這種常見行為讓微服務(wù)的提倡者拒絕打上SOA的標(biāo)簽梯澜,盡管有人認(rèn)為微服務(wù)是從SOA中發(fā)展而來的,或許面向服務(wù)是對的渴析。無論如何晚伙,事實(shí)上SOA表達(dá)這么多的含義,它給一個團(tuán)隊(duì)清醒的認(rèn)識到這種構(gòu)架風(fēng)格就已經(jīng)值的了俭茧。
多語言咆疗,多選擇
JVM做為一個平臺,它的增長就是一個平臺中運(yùn)行多語言的最大的例子母债。過去二十年中午磁,它通常做為更高層次語言的殼,以達(dá)到更高層次的抽象场斑。比如漓踢,研究它的內(nèi)部結(jié)構(gòu)牵署,漏隐、使用低級的語言寫更高效的代碼。盡管如此奴迅,許多整體風(fēng)格并不需要這種層次的性能優(yōu)化或者在語法及高層次上的抽象青责,這很常見(讓我們很失望)挺据。此外整體構(gòu)架通常意味著使用單一的語言,這也限制著使用技術(shù)的數(shù)量脖隶。
實(shí)踐標(biāo)準(zhǔn)和強(qiáng)制標(biāo)準(zhǔn)
它有點(diǎn)尷尬扁耐,微服務(wù)團(tuán)隊(duì)傾向于避免這種通常由企業(yè)架構(gòu)隊(duì)伍定制的僵硬的強(qiáng)制標(biāo)準(zhǔn),但是它們卻非常樂于甚至推廣這些開放的標(biāo)準(zhǔn)产阱,如HTTP婉称、ATOM、其它微規(guī)范构蹬。
關(guān)鍵的不同在這些標(biāo)準(zhǔn)是怎么開發(fā)出來的王暗,以及它們是怎么被推廣的。標(biāo)準(zhǔn)被一些組件管理庄敛,如IETF認(rèn)證標(biāo)準(zhǔn)俗壹,僅當(dāng)它們在互聯(lián)網(wǎng)上有幾個在用的實(shí)現(xiàn),通常源自于開源工程的成功應(yīng)用藻烤。
這些標(biāo)準(zhǔn)單獨(dú)分離出來绷雏,與那種在企業(yè)中通常有沒有什么編碼經(jīng)驗(yàn)的或者沒有什么影響力的廠商標(biāo)準(zhǔn)進(jìn)行區(qū)別。
讓做對事更容易
一方面怖亭,我們發(fā)現(xiàn)在持續(xù)發(fā)布涎显、部署越來越多的使用自動化,是很多有用的工具開發(fā)出來幫助開發(fā)者和運(yùn)營商的努力結(jié)果兴猩。為打包棺禾、代碼管理、支撐服務(wù)的工具峭跳,或者增加標(biāo)準(zhǔn)監(jiān)控的記錄的工具膘婶,現(xiàn)在都非常常見了。網(wǎng)絡(luò)中最好的蛀醉,可能就是Netflix’s的開源工具悬襟,但是包含Dropwizard在內(nèi)的其它工具也被廣泛的使用著。
斷路器(circuit breaker)和產(chǎn)品中現(xiàn)有的代碼
斷路器(circuit breaker)出現(xiàn)在《Realease It!》一書中拯刁,與Bulkhead和Timeout這樣的模式放在一起脊岳。實(shí)施起來,這些模式用于構(gòu)建通信應(yīng)用時(shí)相當(dāng)?shù)闹匾獠!etflix的博客在解釋它們的應(yīng)用時(shí)割捅,做了大量的工作。
同步是有害的
任務(wù)時(shí)候帚桩,你在服務(wù)間的調(diào)用使用同步的方法亿驾,都會遇到宕機(jī)時(shí)間的乘積效應(yīng)。簡單的說账嚎,你的系統(tǒng)宕機(jī)時(shí)間是你系統(tǒng)的單獨(dú)組件的宕機(jī)時(shí)間的乘積莫瞬。你面臨的選擇使用異步或者管理宕機(jī)時(shí)間儡蔓。在www.guardian.co.uk中,它們在新平臺中使用一種簡單的規(guī)則來實(shí)現(xiàn)它:在Netflix中每次用戶請求的同步調(diào)用疼邀,他們重新設(shè)計(jì)的平臺API都會把它構(gòu)建成異步的API來執(zhí)行喂江。
本文作者:船長&CAP
原文鏈接:http://www.cnblogs.com/liuning8023/p/4493156.html
版權(quán)歸作者所有,轉(zhuǎn)載請注明出處