0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

微服務(wù)架構(gòu)中的服務(wù)之間如何互相調(diào)用呢?

jf_ro2CN3Fa ? 來源:CSDN ? 2023-01-31 09:46 ? 次閱讀

在微服務(wù)架構(gòu)中,需要調(diào)用很多服務(wù)才能完成一項(xiàng)功能。服務(wù)之間如何互相調(diào)用就變成微服務(wù)架構(gòu)中的一個(gè)關(guān)鍵問題。

服務(wù)調(diào)用有兩種方式,一種是RPC方式,另一種是事件驅(qū)動(dòng)(Event-driven)方式,也就是發(fā)消息方式。

消息方式是松耦合方式,比緊耦合的RPC方式要優(yōu)越,但RPC方式如果用在適合的場(chǎng)景也有它的一席之地。

我們總在談耦合,那么耦合到底意味著什么呢?

耦合的種類:

時(shí)間耦合: 客戶端和服務(wù)端必須同時(shí)上線才能工作。發(fā)消息時(shí),接受消息隊(duì)列必須運(yùn)行,但后臺(tái)處理程序暫時(shí)不工作也不影響。

容量耦合: 客戶端和服務(wù)端的處理容量必須匹配。發(fā)消息時(shí),如果后臺(tái)處理能力不足也不要緊,消息隊(duì)列會(huì)起到緩沖的作用。

接口耦合: RPC調(diào)用有函數(shù)標(biāo)簽,而消息隊(duì)列只是一個(gè)消息。例如買了商品之后要調(diào)用發(fā)貨服務(wù),如果是發(fā)消息,那么就只需發(fā)送一個(gè)商品被買消息。

發(fā)送方式耦合: RPC是點(diǎn)對(duì)點(diǎn)方式,需要知道對(duì)方是誰,它的好處是能夠傳回返回值。消息既可以點(diǎn)對(duì)點(diǎn),也可以用廣播的方式,這樣減少了耦合,但也使返回值比較困難。

下面我們來逐一分析這些耦合的影響。第一,時(shí)間耦合,對(duì)于多數(shù)應(yīng)用來講,你希望能馬上得到回答,因此即使使用消息隊(duì)列,后臺(tái)也需要一直工作。

第二,容量耦合,如果你對(duì)回復(fù)有時(shí)間要求,那么消息隊(duì)列的緩沖功能作用不大,因?yàn)槟阆M皶r(shí)響應(yīng)。

真正需要的是自動(dòng)伸縮(Auto-scaling),它能自動(dòng)調(diào)整服務(wù)端處理能力去匹配請(qǐng)求數(shù)量。第三和第四,接口耦合和發(fā)送方式耦合,這兩個(gè)確實(shí)是RPC方式的軟肋。

事件驅(qū)動(dòng)(Event-Driven)方式

Martin Fowler把事件驅(qū)動(dòng)分成四種方式(What do you mean by “Event-Driven”),簡(jiǎn)化之后本質(zhì)上只有兩種方式。一種就是我們熟悉的的事件通知(Event Notification),另一種是事件溯源(Event Sourcing)。

事件通知就是微服務(wù)之間不直接調(diào)用,而是通過發(fā)消息來進(jìn)行合作。事件溯源有點(diǎn)像記賬,它把所有的事件都記錄下來,作為永久存儲(chǔ)層,再在它的基礎(chǔ)之上構(gòu)建應(yīng)用程序。

實(shí)際上從應(yīng)用的角度來講,它們并不應(yīng)該分屬一類,它們的用途完全不同。事件通知是微服務(wù)的調(diào)用(或集成)方式,應(yīng)該和RPC分在一起。事件溯源是一種存儲(chǔ)數(shù)據(jù)的方式,應(yīng)該和數(shù)據(jù)庫(kù)分在一起。

事件通知(Event Notification)方式

讓我們用具體的例子來看一下。在下面的例子中,有三個(gè)微服務(wù),“Order Service”, “Customer Service” 和“Product Service”。

4d8b788e-a07c-11ed-bfe3-dac502259ad0.jpg

先說讀數(shù)據(jù),假設(shè)要?jiǎng)?chuàng)建一個(gè)“Order”,在這個(gè)過程中需要讀取“Customer”的數(shù)據(jù)和“Product”數(shù)據(jù)。

如果用事件通知的方式就只能在“Order Service”本地也創(chuàng)建只讀“Customer”和“Product”表,并把數(shù)據(jù)用消息的方式同步過來。

再說寫數(shù)據(jù),如果在創(chuàng)建一個(gè)“Order”時(shí)需要?jiǎng)?chuàng)建一個(gè)新的“Customer”或要修改“Customer”的信息,那么可以在界面上跳轉(zhuǎn)到用戶創(chuàng)建頁(yè)面,然后在“Customer Service”創(chuàng)建用戶之后再發(fā)”用戶已創(chuàng)建“的消息,“Order Service”接到消息,更新本地“Customer”表。

這并不是一個(gè)很好的使用事件驅(qū)動(dòng)的例子,因?yàn)槭录?qū)動(dòng)的優(yōu)點(diǎn)就是不同的程序之間可以獨(dú)立運(yùn)行,沒有綁定關(guān)系。但現(xiàn)在“Order Service”需要等待“Customer Service”創(chuàng)建完了之后才能繼續(xù)運(yùn)行,來完成整個(gè)創(chuàng)建“Order”的工作。主要是因?yàn)椤癘rder”和“Customer”本身從邏輯上來講就是緊耦合關(guān)系,沒有“Customer”你是不能創(chuàng)建“Order”的。

在這種緊耦合的情況下,也可以使用RPC。你可以建立一個(gè)更高層級(jí)的管理程序來管理這些微服務(wù)之間的調(diào)用,這樣“Order Service”就不必直接調(diào)用“Customer Service”了。

當(dāng)然它從本質(zhì)上來講并沒有解除耦合,只是把耦合轉(zhuǎn)移到了上一層,但至少現(xiàn)在“order Service”和“Customer Service”可以互不影響了。之所以不能根除這種緊耦合關(guān)系是因?yàn)樗鼈冊(cè)跇I(yè)務(wù)上是緊耦合的。

再舉一個(gè)購(gòu)物的例子。用戶選好商品之后進(jìn)行“Checkout”,生成“Order”,然后需要“payment”,再?gòu)摹癐nventory”取貨,最后由“Shipment”發(fā)貨,它們每一個(gè)都是微服務(wù)。這個(gè)例子用RPC方式和事件通知方式都可以完成。

當(dāng)用RPC方式時(shí),由“Order”服務(wù)調(diào)用其他幾個(gè)服務(wù)來完成整個(gè)功能。用事件通知方式時(shí),“Checkout”服務(wù)完成之后發(fā)送“Order Placed”消息,“Payment”服務(wù)收到消息,接收用戶付款,發(fā)送“Payment received”消息。

“Inventory”服務(wù)收到消息,從倉(cāng)庫(kù)里取貨,并發(fā)送“Goods fetched”消息?!癝hipment”服務(wù)得到消息,發(fā)送貨物,并發(fā)送“Goods shipped”消息。

4d98d47a-a07c-11ed-bfe3-dac502259ad0.png

對(duì)這個(gè)例子來講,使用事件驅(qū)動(dòng)是一個(gè)不錯(cuò)的選擇,因?yàn)槊總€(gè)服務(wù)發(fā)消息之后它不需要任何反饋,這個(gè)消息由下一個(gè)模塊接收來完成下一步動(dòng)作,時(shí)間上的要求也比上一個(gè)要寬松。用事件驅(qū)動(dòng)的好處是降低了耦合度,壞處是你現(xiàn)在不能在程序里找到整個(gè)購(gòu)物過程的步驟。

如果一個(gè)業(yè)務(wù)邏輯有它自己相對(duì)固定的流程和步驟,那么使用RPC或業(yè)務(wù)流程管理(BPM)能夠更方便地管理這些流程。在這種情況下選哪種方案呢?在我看來好處和壞處是大致相當(dāng)?shù)?。從技術(shù)上來講要選事件驅(qū)動(dòng),從業(yè)務(wù)上來講要選RPC。不過現(xiàn)在越來越多的人采用事件通知作為微服務(wù)的集成方式,它似乎已經(jīng)成了微服務(wù)之間的標(biāo)椎調(diào)用方式。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

事件溯源(Event Sourcing)

這是一種具有顛覆性質(zhì)的的設(shè)計(jì),它把系統(tǒng)中所有的數(shù)據(jù)都以事件(Event)的方式記錄下來,它的持久存儲(chǔ)叫Event Store, 一般是建立在數(shù)據(jù)庫(kù)或消息隊(duì)列(例如Kafka)基礎(chǔ)之上,并提供了對(duì)事件進(jìn)行操作的接口,例如事件的讀寫和查詢。事件溯源是由領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven Design)提出來的。

DDD中有一個(gè)很重要的概念,有界上下文(Bounded Context),可以用有界上下文來劃分微服務(wù),每個(gè)有界上下文都可以是一個(gè)微服務(wù)。下面是有界上下文的示例。下圖中有兩個(gè)服務(wù)“Sales”和“Support”。

有界上下文的一個(gè)關(guān)鍵是如何處理共享成員, 在圖中是“Customer”和“Product”。在不同的有界上下文中,共享成員的含義、用法以及他們的對(duì)象屬性都會(huì)有些不同,DDD建議這些共享成員在各自的有界上下文中都分別建自己的類(包括數(shù)據(jù)庫(kù)表),而不是共享。可以通過數(shù)據(jù)同步的手段來保持?jǐn)?shù)據(jù)的一致性。下面還會(huì)詳細(xì)講解。

4da66a04-a07c-11ed-bfe3-dac502259ad0.png

事件溯源是微服務(wù)的一種存儲(chǔ)方式,它是微服務(wù)的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。因此你可以決定哪些微服務(wù)采用事件溯源方式,哪些不采用,而不必所有的服務(wù)都變成事件溯源的。通常整個(gè)應(yīng)用程序只有一個(gè)Event Store, 不同的微服務(wù)都通過向Event Store發(fā)送和接受消息而互相通信。

Event Store內(nèi)部可以分成不同的stream(相當(dāng)于消息隊(duì)列中的Topic), 供不同的微服務(wù)中的領(lǐng)域?qū)嶓w(Domain Entity)使用。

事件溯源的一個(gè)短板是數(shù)據(jù)查詢,它有兩種方式來解決。第一種是直接對(duì)stream進(jìn)行查詢,這只適合stream比較小并且查詢比較簡(jiǎn)單的情況。

查詢復(fù)雜的話,就要采用第二種方式,那就是建立一個(gè)只讀數(shù)據(jù)庫(kù),把需要的數(shù)據(jù)放在庫(kù)中進(jìn)行查詢。數(shù)據(jù)庫(kù)中的數(shù)據(jù)通過監(jiān)聽Event Store中相關(guān)的事件來更新。

數(shù)據(jù)庫(kù)存儲(chǔ)方式只能保存當(dāng)前狀態(tài),而事件溯源則存儲(chǔ)了所有的歷史狀態(tài),因而能根據(jù)需要回放到歷史上任何一點(diǎn)的狀態(tài),具有很大優(yōu)勢(shì)。但它也不是一點(diǎn)問題都沒有。

第一,它的程序比較復(fù)雜,因?yàn)槭录且坏裙?,你必須把業(yè)務(wù)邏輯按照事件的方式整理出來,然后用事件來驅(qū)動(dòng)程序。第二,如果你要想修改事件或事件的格式就比較麻煩,因?yàn)榕f的事件已經(jīng)存儲(chǔ)在Event Store里了(事件就像日志,是只讀的),沒有辦法再改。

由于事件溯源和事件通知表面上看起來很像,不少人都搞不清楚它們的區(qū)別。事件通知只是微服務(wù)的集成方式,程序內(nèi)部是不使用事件溯源的,內(nèi)部實(shí)現(xiàn)仍然是傳統(tǒng)的數(shù)據(jù)庫(kù)方式。

只有當(dāng)要與其他微服務(wù)集成時(shí)才會(huì)發(fā)消息。而在事件溯源中,事件是一等公民,可以不要數(shù)據(jù)庫(kù),全部數(shù)據(jù)都是按照事件的方式存儲(chǔ)的。

雖然事件溯源的踐行者有不同的意見,但有不少人都認(rèn)為事件溯源不是微服務(wù)的集成方式,而是微服務(wù)的一種內(nèi)部實(shí)現(xiàn)方式。因此,在一個(gè)系統(tǒng)中,可以某些微服務(wù)用事件溯源,另外一些微服務(wù)用數(shù)據(jù)庫(kù)。

當(dāng)你要集成這些微服務(wù)時(shí),你可以用事件通知的方式。注意現(xiàn)在有兩種不同的事件需要區(qū)分開,一種是微服務(wù)的內(nèi)部事件,是顆粒度比較細(xì)的,這種事件只發(fā)送到這個(gè)微服務(wù)的stream中,只被事件溯源使用。

另一種是其他微服務(wù)也關(guān)心的,是顆粒度比較粗的,這種事件會(huì)放到另外一個(gè)或幾個(gè)stream中,被多個(gè)微服務(wù)使用,是用來做服務(wù)之間集成的。這樣做的好處是限制了事件的作用范圍,減少了不相關(guān)事件對(duì)程序的干擾。詳見"Domain Events vs. Event Sourcing"。

事件溯源出現(xiàn)已經(jīng)很長(zhǎng)時(shí)間了,雖然熱度一直在上升(尤其是這兩年),但總的來說非常緩慢,談?wù)摰娜瞬簧?,但生產(chǎn)環(huán)境使用的不多。究其原因就是應(yīng)為它對(duì)現(xiàn)在的體系結(jié)構(gòu)顛覆太大,需要更改數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)和程序的工作方式,還是有一定風(fēng)險(xiǎn)的。

另外,微服務(wù)已經(jīng)形成了一整套體系,從程序部署,服務(wù)發(fā)現(xiàn)與注冊(cè),到監(jiān)控,服務(wù)韌性(Service Resilience),它們基本上都是針對(duì)RPC的,雖然也支持消息,但成熟度就差多了,因此有不少工作還是要自己來做。

有意思的是Kafka一直在推動(dòng)它作為事件驅(qū)動(dòng)的工具,也取得了很大的成功。但它卻沒有得到事件溯源圈內(nèi)的認(rèn)可。

多數(shù)事件溯源都使用一個(gè)叫evenstore的開源Event Store,或是基于某個(gè)數(shù)據(jù)庫(kù)的Event Store,只有比較少的人用Kafka做Event Store。

但如果用Kafka實(shí)現(xiàn)事件通知就一點(diǎn)問題都沒有。總的來說,對(duì)大多數(shù)公司來講事件溯源是有一定挑戰(zhàn)的,應(yīng)用時(shí)需要找到合適的場(chǎng)景。如果你要嘗試的話,可以先拿一個(gè)微服務(wù)試水。

雖然現(xiàn)在事件驅(qū)動(dòng)還有些生澀,但從長(zhǎng)遠(yuǎn)來講,還是很看好它的。像其他全新的技術(shù)一樣,事件溯源需要大規(guī)模的適用場(chǎng)景來推動(dòng)。例如容器技術(shù)就是因?yàn)槲⒎?wù)的流行和推動(dòng),才走向主流。

事件溯源以前的適用場(chǎng)景只限于記賬和源代碼庫(kù),局限性較大。區(qū)塊鏈可能會(huì)成為它的下一個(gè)機(jī)遇,因?yàn)樗玫囊彩鞘录菰醇夹g(shù)。

另外AI今后會(huì)滲入到具體程序中,使程序具有學(xué)習(xí)功能。而RPC模式注定沒有自適應(yīng)功能。事件驅(qū)動(dòng)本身就具有對(duì)事件進(jìn)行反應(yīng)的能力,這是自我學(xué)習(xí)的基礎(chǔ)。因此,這項(xiàng)技術(shù)長(zhǎng)遠(yuǎn)來講定會(huì)大放異彩,但短期內(nèi)(3-5年)大概不會(huì)成為主流。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

RPC方式

RPC的方式就是遠(yuǎn)程函數(shù)調(diào)用,像RESTFul,gRPC, DUBBO 都是這種方式。它一般是同步的,可以馬上得到結(jié)果。在實(shí)際中,大多數(shù)應(yīng)用都要求立刻得到結(jié)果,這時(shí)同步方式更有優(yōu)勢(shì),代碼也更簡(jiǎn)單。

服務(wù)網(wǎng)關(guān)(API Gateway)

熟悉微服務(wù)的人可能都知道服務(wù)網(wǎng)關(guān)(API Gateway)。當(dāng)UI需要調(diào)用很多微服務(wù)時(shí),它需要了解每個(gè)服務(wù)的接口,這個(gè)工作量很大。

于是就用服務(wù)網(wǎng)關(guān)創(chuàng)建了一個(gè)Facade,把幾個(gè)微服務(wù)封裝起來,這樣UI就只調(diào)用服務(wù)網(wǎng)關(guān)就可以了,不需要去對(duì)付每一個(gè)微服務(wù)。下面是API Gateway示例圖:

4db3c5f0-a07c-11ed-bfe3-dac502259ad0.jpg

服務(wù)網(wǎng)關(guān)(API Gateway)不是為了解決微服務(wù)之間調(diào)用的緊耦合問題,它主要是為了簡(jiǎn)化客戶端的工作。其實(shí)它還可以用來降低函數(shù)之間的耦合度。

有了API Gateway之后,一旦服務(wù)接口修改,你可能只需要修改API Gateway, 而不必修改每個(gè)調(diào)用這個(gè)函數(shù)的客戶端,這樣就減少了程序的耦合性。

服務(wù)調(diào)用

可以借鑒API Gateway的思路來減少RPC調(diào)用的耦合度,例如把多個(gè)微服務(wù)組織起來形成一個(gè)完整功能的服務(wù)組合,并對(duì)外提供統(tǒng)一的服務(wù)接口。這種想法跟上面的API Gateway有些相似,都是把服務(wù)集中起來提供粗顆粒(Coarse Granular)服務(wù),而不是細(xì)顆粒的服務(wù)(Fine Granular)。

但這樣建立的服務(wù)組合可能只適合一個(gè)程序使用,沒有多少共享價(jià)值。因此如果有合適的場(chǎng)景就采用,否側(cè)也不必強(qiáng)求。雖然我們不能降低RPC服務(wù)之間的耦合度,卻可以減少這種緊耦合帶來的影響。

降低緊耦合的影響

什么是緊耦合的主要問題呢?就是客戶端和服務(wù)端的升級(jí)不同步。服務(wù)端總是先升級(jí),客戶端可能有很多,如果要求它們同時(shí)升級(jí)是不現(xiàn)實(shí)的。它們有各自的部署時(shí)間表,一般都會(huì)選擇在下一次部署時(shí)順帶升級(jí)。

一般有兩個(gè)辦法可以解決這個(gè)問題:

同時(shí)支持多個(gè)版本:這個(gè)工作量比較大,因此大多數(shù)公司都不會(huì)采用這種方式。

服務(wù)端向后兼容:這是更通用的方式。例如你要加一個(gè)新功能或有些客戶要求給原來的函數(shù)增加一個(gè)新的參數(shù),但別的客戶不需要這個(gè)參數(shù)。這時(shí)你只好新建一個(gè)函數(shù),跟原來的功能差不多,只是多了一個(gè)參數(shù)。這樣新舊客戶的需求都能滿足。它的好處是向后兼容(當(dāng)然這取決于你使用的協(xié)議)。

它的壞處是當(dāng)以后新的客戶來了,看到兩個(gè)差不多的函數(shù)就糊涂了,不知道該用那個(gè)。而且時(shí)間越長(zhǎng)越嚴(yán)重,你的服務(wù)端可能功能增加的不多,但相似的函數(shù)卻越來越多,無法選擇。

它的解決辦法就是使用一個(gè)支持向后兼容的RPC協(xié)議,現(xiàn)在最好的就是Protobuf gRPC,尤其是在向后兼容上。

它給每個(gè)服務(wù)定義了一個(gè)接口,這個(gè)接口是與編程語言無關(guān)的中性接口,然后你可以用工具生成各個(gè)語言的實(shí)現(xiàn)代碼,供不同語言使用。函數(shù)定義的變量都有編號(hào),變量可以是可選類型的,這樣就比較好地解決了函數(shù)兼容的問題。

就用上面的例子,當(dāng)你要增加一個(gè)可選參數(shù)時(shí),你就定義一個(gè)新的可選變量。由于它是可選的,原來的客戶端不需要提供這個(gè)參數(shù),因此不需要修改程序。

而新的客戶端可以提供這個(gè)參數(shù)。你只要在服務(wù)端能同時(shí)處理這兩種情況就行了。這樣服務(wù)端并沒有增加新的函數(shù),但用戶的新需求滿足了,而且還是向后兼容的。

微服務(wù)的數(shù)量有沒有上限?

總的來說微服務(wù)的數(shù)量不要太多,不然會(huì)有比較重的運(yùn)維負(fù)擔(dān)。有一點(diǎn)需要明確的是微服務(wù)的流行不是因?yàn)榧夹g(shù)上的創(chuàng)新,而是為了滿足管理上的需要。單體程序大了之后,各個(gè)模塊的部署時(shí)間要求不同,對(duì)服務(wù)器的優(yōu)化要求也不同,而且團(tuán)隊(duì)人數(shù)眾多,很難協(xié)調(diào)管理。

把程序拆分成微服務(wù)之后,每個(gè)團(tuán)隊(duì)負(fù)責(zé)幾個(gè)服務(wù),就容易管理了,而且每個(gè)團(tuán)隊(duì)也可以按照自己的節(jié)奏進(jìn)行創(chuàng)新,但它給運(yùn)維帶來了巨大的麻煩。所以在微服務(wù)剛出來時(shí),我一直覺得它是一個(gè)退步,弊大于利。但由于管理上的問題沒有其他解決方案,只有硬著頭皮上了。

值得慶幸的是微服務(wù)帶來的麻煩都是可解的。直到后來,微服務(wù)建立了全套的自動(dòng)化體系,從程序集成到部署,從全鏈路跟蹤到日志,以及服務(wù)檢測(cè),服務(wù)發(fā)現(xiàn)和注冊(cè),這樣才把微服務(wù)的工作量降了下來。

雖然微服務(wù)在技術(shù)上一無是處,但它的流行還是大大推動(dòng)了容器技術(shù),服務(wù)網(wǎng)格(Service Mesh)和全鏈路跟蹤等新技術(shù)的發(fā)展。不過它本身在技術(shù)上還是沒有發(fā)現(xiàn)任何優(yōu)勢(shì)。

直到有一天,我意識(shí)到單體程序其實(shí)性能調(diào)試是很困難的(很難分離出瓶頸點(diǎn)),而微服務(wù)配置了全鏈路跟蹤之后,能很快找到癥結(jié)所在??磥砦⒎?wù)從技術(shù)來講也不全是缺點(diǎn),總算也有好的地方。但微服務(wù)的顆粒度不宜過細(xì),否則工作量還是太大。

一般規(guī)模的公司十幾個(gè)或幾十個(gè)微服務(wù)都是可以承受的,但如果有幾百個(gè)甚至上千個(gè),那么絕不是一般公司可以管理的。盡管現(xiàn)有的工具已經(jīng)很齊全了,而且與微服務(wù)有關(guān)的整個(gè)流程也已經(jīng)基本上全部自動(dòng)化了,但它還是會(huì)增加很多工作。

Martin Fowler幾年以前建議先從單體程序開始(詳見 MonolithFirst),然后再逐步把功能拆分出去,變成一個(gè)個(gè)的微服務(wù)。但是后來有人反對(duì)這個(gè)建議,他也有些松口了。

如果單體程序不是太大,這是個(gè)好主意。可以用數(shù)據(jù)額庫(kù)表的數(shù)量來衡量程序的大小,我見過大的單體程序有幾百?gòu)埍?,這就太多了,很難管理。正常情況下,一個(gè)微服務(wù)可以有兩、三張表到五、六張表,一般不超過十張表。但如果要減少微服務(wù)數(shù)量的話,可以把這個(gè)標(biāo)準(zhǔn)放寬到不要超過二十張表。

用這個(gè)做為大致的指標(biāo)來創(chuàng)建微程序,如果使用一段時(shí)間之后還是覺得太大了,那么再逐漸拆分。當(dāng)然,按照這個(gè)標(biāo)準(zhǔn)建立的服務(wù)更像是服務(wù)組合,而不是單個(gè)的微服務(wù)。不過它會(huì)為你減少工作量。只要不影響業(yè)務(wù)部門的創(chuàng)新進(jìn)度,這是一個(gè)不錯(cuò)的方案。

到底應(yīng)不應(yīng)該選擇微服務(wù)呢?如果單體程序已經(jīng)沒法管理了,那么你別無選擇。如果沒有管理上的問題,那么微服務(wù)帶給你的只有問題和麻煩。其實(shí),一般公司都沒有太多選擇,只能采用微服務(wù),不過你可以選擇建立比較少的微服務(wù)。如果還是沒法決定,有一個(gè)折中的方案,“內(nèi)部微服務(wù)設(shè)計(jì)”。

內(nèi)部微服務(wù)設(shè)計(jì)

這種設(shè)計(jì)表面上看起來是一個(gè)單體程序,它只有一個(gè)源代碼存儲(chǔ)倉(cāng)庫(kù),一個(gè)數(shù)據(jù)庫(kù),一個(gè)部署,但在程序內(nèi)部可以按照微服務(wù)的思想來進(jìn)行設(shè)計(jì)。它可以分成多個(gè)模塊,每個(gè)模塊是一個(gè)微服務(wù),可以由不同的團(tuán)隊(duì)管理。

4dbda232-a07c-11ed-bfe3-dac502259ad0.png

用這張圖做例子。這個(gè)圖里的每個(gè)圓角方塊大致是一個(gè)微服務(wù),但我們可以把它作為一個(gè)單體程序來設(shè)計(jì),內(nèi)部有五個(gè)微服務(wù)。

每個(gè)模塊都有自己的數(shù)據(jù)庫(kù)表,它們都在一個(gè)數(shù)據(jù)庫(kù)中,但模塊之間不能跨數(shù)據(jù)庫(kù)訪問(不要建立模塊之間數(shù)據(jù)庫(kù)表的外鍵)。

“User”(在Conference Management模塊中)是一個(gè)共享的類,但在不同的模塊中的名字不同,含義和用法也不同,成員也不一樣(例如,在“Customer Service”里叫“Customer”)。

DDD(Domain-Driven Design)建議不要共享這個(gè)類,而是在每一個(gè)有界上下文(模塊)中都建一個(gè)新類,并擁有新的名字。

雖然它們的數(shù)據(jù)庫(kù)中的數(shù)據(jù)應(yīng)該大致相同,但DDD建議每一個(gè)有界上下文中都建一個(gè)新表,它們之間再進(jìn)行數(shù)據(jù)同步。

這個(gè)所謂的“內(nèi)部微服務(wù)設(shè)計(jì)”其實(shí)就是DDD,但當(dāng)時(shí)還沒有微服務(wù),因此外表看起來是單體程序,但內(nèi)部已經(jīng)是微服務(wù)的設(shè)計(jì)了。

它的書在2003就出版了,當(dāng)時(shí)就很有名。但它更偏重于業(yè)務(wù)邏輯的設(shè)計(jì),踐行起來也比較困難,因此大家談?wù)摰煤芏?,真正用的較少。

直到十年之后,微服務(wù)出來之后,人們發(fā)現(xiàn)它其實(shí)內(nèi)部就是微服務(wù),而且微服務(wù)的設(shè)計(jì)需要用它的思想來指導(dǎo),于是就又重新煥發(fā)了青春,而且這次更猛,已經(jīng)到了每個(gè)談?wù)撐⒎?wù)的人都不得不談?wù)揇DD的地步。不過一本軟件書籍,在十年之后還能指導(dǎo)新技術(shù)的設(shè)計(jì),非常令人欽佩。

這樣設(shè)計(jì)的好處是它是一個(gè)單體程序,省去了多個(gè)微服務(wù)帶來的部署、運(yùn)維的麻煩。但它內(nèi)部是按微服務(wù)設(shè)計(jì)的,如果以后要拆分成微服務(wù)會(huì)比較容易。至于什么時(shí)候拆分不是一個(gè)技術(shù)問題。

如果負(fù)責(zé)這個(gè)單體程序的各個(gè)團(tuán)隊(duì)之間不能在部署時(shí)間表,服務(wù)器優(yōu)化等方面達(dá)成一致,那么就需要拆分了。

當(dāng)然你也要應(yīng)對(duì)隨之而來的各種運(yùn)維麻煩。內(nèi)部微服務(wù)設(shè)計(jì)是一個(gè)折中的方案,如果你想試水微服務(wù),但又不愿意冒太大風(fēng)險(xiǎn)時(shí),這是一個(gè)不錯(cuò)的選擇。

結(jié)論

微服務(wù)之間的調(diào)用有兩種方式,RPC和事件驅(qū)動(dòng)。事件驅(qū)動(dòng)是更好的方式,因?yàn)樗撬神詈系?。但如果業(yè)務(wù)邏輯是緊耦合的,RPC方式也是可行的(它的好處是代碼更簡(jiǎn)單),而且你還可以通過選取合適的協(xié)議(Protobuf gRPC)來降低這種緊耦合帶來的危害。

由于事件溯源和事件通知的相似性,很多人把兩者弄混了,但它們實(shí)際上是完全不同的東西。微服務(wù)的數(shù)量不宜太多,可以先創(chuàng)建比較大的微服務(wù)(更像是服務(wù)組合)。

如果你還是不能確定是否采用微服務(wù)架構(gòu),可以先從“內(nèi)部微服務(wù)設(shè)計(jì)”開始,再逐漸拆分。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RPC
    RPC
    +關(guān)注

    關(guān)注

    0

    文章

    110

    瀏覽量

    11483
  • BPM
    BPM
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    8067
  • 緊耦合
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    923

原文標(biāo)題:難住了,微服務(wù)之間的幾種調(diào)用方式哪種最佳?

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    微服務(wù)架構(gòu)和CQRS架構(gòu)基本概念介紹

    邊界思維,微服務(wù)的目的是為了從業(yè)務(wù)角度拆分(職責(zé)分離)當(dāng)前業(yè)務(wù)領(lǐng)域的不同業(yè)務(wù)模塊到不同的服務(wù),每個(gè)微服務(wù)之間的數(shù)據(jù)完全獨(dú)立,它們之間的交互可
    發(fā)表于 05-22 09:03

    微服務(wù)架構(gòu)與實(shí)踐摘要

    本文主要類容是對(duì)微服務(wù)架構(gòu)與實(shí)踐摘要解析。微服務(wù)架構(gòu)的 “微” 體現(xiàn)了其核心要素,即服務(wù)的微型
    的頭像 發(fā)表于 02-07 16:57 ?6073次閱讀
    <b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>與實(shí)踐摘要

    微服務(wù)優(yōu)勢(shì)_微服務(wù)架構(gòu)的好處與不足

    微服務(wù)是用一組小服務(wù)的方式來構(gòu)建一個(gè)應(yīng)用,服務(wù)獨(dú)立運(yùn)行在不同的進(jìn)程服務(wù)之間通過輕量的通訊機(jī)制
    發(fā)表于 02-23 11:24 ?4371次閱讀

    微服務(wù)架構(gòu)與實(shí)踐基礎(chǔ)篇

    微服務(wù)架構(gòu),應(yīng)用程序由多個(gè)服務(wù)組成,每個(gè)服務(wù)都是高度自治的獨(dú)立業(yè)務(wù)實(shí)體,可以運(yùn)行在獨(dú)立的進(jìn)程
    的頭像 發(fā)表于 04-10 14:23 ?4197次閱讀
    <b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>與實(shí)踐基礎(chǔ)篇

    微服務(wù)和容器之間的有何關(guān)系?

    現(xiàn)在一提到微服務(wù),有很多人會(huì)想到容器技術(shù)(這里說到的容器技術(shù)是指docker)。那么微服務(wù)和容器之間到底有什么關(guān)系,我來簡(jiǎn)要和大家探討下。先拋出結(jié)論:
    的頭像 發(fā)表于 02-01 01:58 ?6081次閱讀

    什么是微服務(wù)架構(gòu)_微服務(wù)架構(gòu)的優(yōu)缺點(diǎn)及應(yīng)用

    什么是微服務(wù)架構(gòu) 簡(jiǎn)單地說,微服務(wù)是系統(tǒng)架構(gòu)上的一種設(shè)計(jì)風(fēng)格, 它的主旨是將一個(gè)原本獨(dú)立的系統(tǒng)拆分成多個(gè)小型服務(wù),這些小型
    的頭像 發(fā)表于 06-02 10:03 ?1.7w次閱讀
    什么是<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>_<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>的優(yōu)缺點(diǎn)及應(yīng)用

    微服務(wù)架構(gòu)有哪些_微服務(wù)架構(gòu)設(shè)計(jì)模式

    小伙伴們知道常用的微服務(wù)架構(gòu)框架有哪些嗎?上回我們介紹了一些常用的微服務(wù)架構(gòu)設(shè)計(jì)模式,這次我們就來了解一下一些常用的微服務(wù)
    的頭像 發(fā)表于 05-17 17:06 ?2.9w次閱讀
    <b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>有哪些_<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>設(shè)計(jì)模式

    微服務(wù)架構(gòu)的特點(diǎn)_微服務(wù)架構(gòu)適用場(chǎng)景

     微服務(wù)架構(gòu)是一項(xiàng)在云中部署應(yīng)用和服務(wù)的新技術(shù)。
    的頭像 發(fā)表于 05-17 17:28 ?4977次閱讀

    微服務(wù)軟件架構(gòu)應(yīng)用研究綜述

    自2014年,微服務(wù)架構(gòu)概念經(jīng)Martin Flower提出以來,受到廣泛關(guān)注,為更好了解微服務(wù)架構(gòu)風(fēng)格,本文首先分析、梳理了軟件架構(gòu)的發(fā)展
    發(fā)表于 05-26 09:26 ?2次下載

    微服務(wù)循環(huán)依賴調(diào)用引發(fā)的血案

    順著測(cè)試匯報(bào)的出現(xiàn)問題的場(chǎng)景,跟蹤調(diào)用鏈上相關(guān)服務(wù)的日志,發(fā)現(xiàn)出現(xiàn)了微服務(wù)之間循依賴調(diào)用。大致情況可以抽象如下所示(圖中所有
    的頭像 發(fā)表于 01-16 10:28 ?658次閱讀

    什么是微服務(wù)架構(gòu)

    在Medium,我們的技術(shù)堆棧始于2012年的單片Node.js應(yīng)用程序。我們已經(jīng)構(gòu)建了幾個(gè)衛(wèi)星服務(wù),但我們還沒有制定一個(gè)系統(tǒng)地采用微服務(wù)架構(gòu)的策略。隨著系統(tǒng)變得越來越復(fù)雜并且團(tuán)隊(duì)不斷發(fā)展,我們?cè)?018年初轉(zhuǎn)向了
    的頭像 發(fā)表于 02-24 11:15 ?1292次閱讀
    什么是<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>?

    從分層架構(gòu)微服務(wù)架構(gòu)介紹(五)

    本文要介紹的是 服務(wù)架構(gòu) (Service-Based Architecture, SBA )。 SBA 可以看成是單體架構(gòu)微服務(wù)架構(gòu)
    的頭像 發(fā)表于 05-10 17:02 ?765次閱讀
    從分層<b class='flag-5'>架構(gòu)</b>到<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>介紹(五)

    springcloud微服務(wù)架構(gòu)

    Spring Cloud是一個(gè)開源的微服務(wù)架構(gòu)框架,它提供了一系列工具和組件,用于構(gòu)建和管理分布式系統(tǒng)微服務(wù)。它基于Spring框架,旨在通過簡(jiǎn)化開發(fā)過程和降低系統(tǒng)復(fù)雜性來幫助開發(fā)
    的頭像 發(fā)表于 11-23 09:24 ?1064次閱讀

    docker微服務(wù)架構(gòu)實(shí)戰(zhàn)

    的容器化技術(shù),為微服務(wù)架構(gòu)的實(shí)施提供了強(qiáng)大的支持。本文將介紹Docker微服務(wù)架構(gòu)的實(shí)戰(zhàn)經(jīng)驗(yàn),包括Docker的概述、微服務(wù)
    的頭像 發(fā)表于 11-23 09:26 ?578次閱讀

    設(shè)計(jì)微服務(wù)架構(gòu)的原則

    微服務(wù)是一種軟件架構(gòu)策略,有利于改善整體性能和可擴(kuò)展性。你可能會(huì)想,我的團(tuán)隊(duì)需不需要采用微服務(wù),設(shè)計(jì)微服務(wù)架構(gòu)有哪些原則?本文會(huì)給你一些靈感
    的頭像 發(fā)表于 11-26 08:05 ?501次閱讀
    設(shè)計(jì)<b class='flag-5'>微服務(wù)</b><b class='flag-5'>架構(gòu)</b>的原則