本文翻譯自 Gero Vermaas 在 voxxed 的博客文章,原文地址:
https://www.voxxed.com/blog/2015/04/coupling-versus-autonomy-in-microservices/
微服務(wù)是一種有望解決以前架構(gòu)風(fēng)格各種問(wèn)題的新架構(gòu)風(fēng)格度气。如同其他架構(gòu)風(fēng)格照棋,微服務(wù)也有其自身的挑戰(zhàn)牡整。本文討論的問(wèn)題是如何解除微服務(wù)之間的耦合并保持微服務(wù)盡可能的自治每辟,這里我們會(huì)討論四種方案并最終選擇一種岩四。
對(duì)我來(lái)說(shuō)礼殊,微服務(wù)是一種要對(duì)業(yè)務(wù)能力完全負(fù)責(zé)的自治服務(wù),這里的完全負(fù)責(zé)是指對(duì)表現(xiàn)層茸时、API贡定、數(shù)據(jù)存儲(chǔ)和業(yè)務(wù)邏輯完全負(fù)責(zé)。我覺得自治是微服務(wù)的關(guān)鍵可都,自治服務(wù)才會(huì)在修改時(shí)對(duì)其他部分造成盡可能小的影響缓待;自治服務(wù)運(yùn)營(yíng)時(shí)也不會(huì)對(duì)其他服務(wù)的功能造成影響。
聽起來(lái)不錯(cuò)渠牲,但是服務(wù)永遠(yuǎn)不會(huì)成為了一個(gè)與世隔絕的孤島旋炒,服務(wù)幾乎總是要依賴其他服務(wù)提供的數(shù)據(jù)。例如签杈,網(wǎng)上商城都有一個(gè)購(gòu)物車微服務(wù)瘫镇,一些其他服務(wù)必須能向購(gòu)物車添加商品,還必須能訪問(wèn)購(gòu)物車內(nèi)的商品并下單和配送∏酆荆現(xiàn)在問(wèn)題是汇四,如何在保持服務(wù)盡可能自治的前提下實(shí)現(xiàn)對(duì)接接奈。本文的目的是介紹幾種在保持微服務(wù)之間最大可能的自治前提下對(duì)接微服務(wù)需要遵循的模式踢涌。
我將從兩個(gè)維度構(gòu)建這些模式:交互模式和信息交換模式。
交互模式:Request-Reply 還是 Publish-Subscribe
![Request-Reply vs. Publish-Subscribe](http://blog.xebia.com/wp-content/uploads/2015/03/rr-ps-e1426428195917.png)
- Request-Reply(請(qǐng)求-應(yīng)答)意味著一個(gè)服務(wù)處理信息的特定請(qǐng)求或者執(zhí)行一些動(dòng)作并返回一個(gè)應(yīng)答序宦。發(fā)起調(diào)用的服務(wù)需要知道去哪兒請(qǐng)求以及請(qǐng)求些什么睁壁?這種模式仍然可以被實(shí)現(xiàn)為異步執(zhí)行,并且你還可以做一些抽象使服務(wù)調(diào)用方不需要知道被調(diào)用服務(wù)的物理地址互捌,不能逃避的一點(diǎn)是服務(wù)必須明確的要求一個(gè)特定的信息和功能(或者執(zhí)行動(dòng)作)并等待應(yīng)答潘明。
- Publish-Subscribe(發(fā)布-訂閱) 這種模式下的服務(wù)將自己注冊(cè)為對(duì)特定的信息感興趣,或者能夠處理特定的請(qǐng)求秕噪,相關(guān)的信息和請(qǐng)求將被交付給它钳降,并且它可以決定怎么處理這些信息和請(qǐng)求。本文假定有一些中間件能夠處理交付或者發(fā)布消息給訂閱這些消息服務(wù)腌巾。
信息交換:Events 還是 Queries/Commands
- Events(事件)是沒(méi)有爭(zhēng)議的事實(shí)遂填,比如訂單號(hào) 123 的訂單已經(jīng)創(chuàng)建,事件只陳述發(fā)生了什么事澈蝙,不描述這樣一個(gè)事件會(huì)導(dǎo)致什么事情發(fā)生吓坚。
- Queries/Commands(查詢/命令)兩者都傳達(dá)了什么事情會(huì)發(fā)生,查詢是對(duì)信息的特定請(qǐng)求灯荧,命令是要求一個(gè)服務(wù)執(zhí)行一些動(dòng)作的特定請(qǐng)求礁击。
把這兩種維度組成矩陣就得到微服務(wù)間對(duì)接的四種方式。那么每種方式的優(yōu)勢(shì)和劣勢(shì)是什么?那種是保持服務(wù)最大化自治的最好方式哆窿?
以下的描述中我們將使用兩個(gè)服務(wù)來(lái)闡述每種方式链烈,訂單服務(wù)負(fù)責(zé)管理訂單,配送服務(wù)負(fù)責(zé)配送訂單里的商品挚躯。這些服務(wù)是網(wǎng)上商店的一部分测垛,網(wǎng)上商店還可能包含一些類似購(gòu)物車、商品目錄(搜索)等服務(wù)秧均。
1. REQUEST-REPLY WITH EVENTS
![REQUEST-REPLY WITH EVENTS](http://blog.xebia.com/wp-content/uploads/2015/03/rre1.png)
在這種模式下食侮,一個(gè)服務(wù)請(qǐng)求另一個(gè)導(dǎo)致事件發(fā)生的特定服務(wù),這意味著這兩種服務(wù)之間有很強(qiáng)的依賴目胡。配送服務(wù)必須知道要連接那個(gè)服務(wù)來(lái)獲得訂單相關(guān)的事件锯七,這也導(dǎo)致了運(yùn)行時(shí)依賴,因?yàn)榕渌头?wù)只有在訂單服務(wù)可用的時(shí)候才能配送新訂單誉己。
既然配送服務(wù)只接收事件眉尸,它基于事件里的信息自己決定何時(shí)一個(gè)訂單可以被配送,訂單服務(wù)不需要知道配送服務(wù)的任何信息巨双,它只是簡(jiǎn)單的提供事件表明當(dāng)其他服務(wù)請(qǐng)求時(shí)訂單進(jìn)行怎樣的處理噪猾,把響應(yīng)事件的職責(zé)完全交給請(qǐng)求事件的服務(wù)。
2. REQUEST-REPLY WITH COMMANDS/QUERIES
![REQUEST-REPLY WITH COMMANDS/QUERIES](http://blog.xebia.com/wp-content/uploads/2015/03/rrc.png)
在這種模式下筑累,訂單服務(wù)將請(qǐng)求配送服務(wù)來(lái)配送一個(gè)訂單袱蜡,這意味著強(qiáng)烈的依賴,因?yàn)橛唵畏?wù)明確的請(qǐng)求一個(gè)特定的服務(wù)來(lái)處理配送慢宗,現(xiàn)在訂單服務(wù)必須決定何時(shí)一個(gè)訂單準(zhǔn)備好配送坪蚁,它意識(shí)到配送服務(wù)的存在,甚至知道怎樣與配送服務(wù)交互镜沽,在訂單配送前需要考慮是否有其他因素關(guān)聯(lián)到訂單(比如客戶信用卡狀態(tài))敏晤,訂單服務(wù)在請(qǐng)求配送服務(wù)來(lái)配送訂單前也需要考慮這一點(diǎn)。現(xiàn)在業(yè)務(wù)處理被混到了架構(gòu)里缅茉,因此架構(gòu)不能被簡(jiǎn)單的修改嘴脾。
這也是運(yùn)行時(shí)依賴,因?yàn)橛唵畏?wù)必須確保配送請(qǐng)求成功交付給了配送服務(wù)蔬墩。
3. PUBLISH-SUBSCRIBE WITH EVENTS
![PUBLISH-SUBSCRIBE WITH EVENTS](http://blog.xebia.com/wp-content/uploads/2015/03/pse1.png)
配送服務(wù)注冊(cè)自己對(duì)訂單相關(guān)的事件感興趣译打,注冊(cè)后,配送服務(wù)會(huì)收到訂單的所有事件而不需要關(guān)心訂單事件的來(lái)源筹我,這是對(duì)訂單事件來(lái)源的松散耦合扶平,配送服務(wù)需要保留接收到事件的副本,這樣就可以決定何時(shí)訂單準(zhǔn)備好配送蔬蕊。
訂單服務(wù)需要對(duì)配送無(wú)關(guān)结澄,如果多個(gè)服務(wù)提供包含配送服務(wù)需要的相關(guān)數(shù)據(jù)的訂單相關(guān)事件哥谷,配送服務(wù)應(yīng)該不可識(shí)別,如果一個(gè)提供訂單事件的服務(wù)宕機(jī)麻献,配送服務(wù)也應(yīng)該不知道们妥,只是收到的事件變少了,配送服務(wù)不會(huì)因此阻塞勉吻。
4. PUBLISH-SUBSCRIBE WITH COMMANDS/QUERIES
![PUBLISH-SUBSCRIBE WITH COMMANDS/QUERIES](http://blog.xebia.com/wp-content/uploads/2015/03/psc.png)
配送服務(wù)自己注冊(cè)為能夠配送貨物的服務(wù)监婶,接受所有想要配送貨物的命令,配送服務(wù)不需要意識(shí)到配送命令的來(lái)源齿桃,同樣訂單服務(wù)業(yè)不知道那些服務(wù)將處理配送惑惶,在這個(gè)意義上說(shuō),他們是松散耦合的短纵,不過(guò)带污,訂單服務(wù)知道既然發(fā)送了配送命令,訂單必須被配送的事實(shí)香到,這確實(shí)讓耦合更強(qiáng)了鱼冀。
結(jié)論
現(xiàn)在我們已經(jīng)描述了四種模式,讓我們回到原來(lái)的問(wèn)題悠就,那種方式更自治千绪?
兩種 Request-Reply 模式都意味著兩個(gè)服務(wù)的運(yùn)行時(shí)耦合和強(qiáng)耦合,兩種 Command/Queries 模式意味著一個(gè)服務(wù)知道另一個(gè)服務(wù)應(yīng)該做的事(我們的例子中訂單服務(wù)知道配送服務(wù)負(fù)責(zé)配送)梗脾,這也意味著強(qiáng)耦合荸型,但是這一次在功能級(jí)別。留下了一個(gè)選項(xiàng):Publish-Subscribe with Events藐唠,這種情況下帆疟,兩種服務(wù)從運(yùn)行時(shí)和功能的角度都沒(méi)有意識(shí)到彼此的存在鹉究。對(duì)我來(lái)說(shuō)這是實(shí)現(xiàn)服務(wù)之間最大的自主權(quán)的贏家宇立。
下一個(gè)問(wèn)題是 - 你應(yīng)該總是使用 Publish-Subscribe with Events?答案是肯定的自赔,但是我們需要考慮更多的因素妈嘹,一直使用這種方式交互是有代價(jià)的,例如绍妨,數(shù)據(jù)被復(fù)制润脸、事件丟失、事件驅(qū)動(dòng)的架構(gòu)增加更多基礎(chǔ)設(shè)施的需求他去、額外的延遲毙驯。
在以后的文章中,我將深入到這些權(quán)衡和正確看待這個(gè)事情≡植猓現(xiàn)在爆价,記住 Publish-Subscribe with Events 是實(shí)現(xiàn)服務(wù)自治的良好基礎(chǔ)。