在微服務(wù)架構(gòu)中,需要調(diào)用很多服務(wù)才能完成一項功能。服務(wù)之間如何互相調(diào)用就變成微服務(wù)架構(gòu)中的一個關(guān)鍵問題。
服務(wù)調(diào)用有兩種方式,一種是RPC方式,另一種是事件驅(qū)動(Event-driven)方式,也就是發(fā)消息方式。
消息方式是松耦合方式,比緊耦合的RPC方式要優(yōu)越,但RPC方式如果用在適合的場景也有它的一席之地。
我們總在談耦合,那么耦合到底意味著什么呢?
耦合的種類:
時間耦合:客戶端和服務(wù)端必須同時上線才能工作。發(fā)消息時,接受消息隊列必須運行,但后臺處理程序暫時不工作也不影響。
容量耦合:客戶端和服務(wù)端的處理容量必須匹配。發(fā)消息時,如果后臺處理能力不足也不要緊,消息隊列會起到緩沖的作用。
接口耦合:RPC調(diào)用有函數(shù)標簽,而消息隊列只是一個消息。例如買了商品之后要調(diào)用發(fā)貨服務(wù),如果是發(fā)消息,那么就只需發(fā)送一個商品被買消息。
發(fā)送方式耦合:RPC是點對點方式,需要知道對方是誰,它的好處是能夠傳回返回值。消息既可以點對點,也可以用廣播的方式,這樣減少了耦合,但也使返回值比較困難。
下面我們來逐一分析這些耦合的影響。第一,時間耦合,對于多數(shù)應(yīng)用來講,你希望能馬上得到回答,因此即使使用消息隊列,后臺也需要一直工作。
第二,容量耦合,如果你對回復(fù)有時間要求,那么消息隊列的緩沖功能作用不大,因為你希望及時響應(yīng)。
真正需要的是自動伸縮(Auto-scaling),它能自動調(diào)整服務(wù)端處理能力去匹配請求數(shù)量。第三和第四,接口耦合和發(fā)送方式耦合,這兩個確實是RPC方式的軟肋。
事件驅(qū)動(Event-Driven)方式
Martin Fowler把事件驅(qū)動分成四種方式(What do you mean by “Event-Driven”),簡化之后本質(zhì)上只有兩種方式。一種就是我們熟悉的的事件通知(Event Notification),另一種是事件溯源(Event Sourcing)。
事件通知就是微服務(wù)之間不直接調(diào)用,而是通過發(fā)消息來進行合作。事件溯源有點像記賬,它把所有的事件都記錄下來,作為永久存儲層,再在它的基礎(chǔ)之上構(gòu)建應(yīng)用程序。
實際上從應(yīng)用的角度來講,它們并不應(yīng)該分屬一類,它們的用途完全不同。事件通知是微服務(wù)的調(diào)用(或集成)方式,應(yīng)該和RPC分在一起。事件溯源是一種存儲數(shù)據(jù)的方式,應(yīng)該和數(shù)據(jù)庫分在一起。
事件通知(Event Notification)方式
讓我們用具體的例子來看一下。在下面的例子中,有三個微服務(wù),“Order Service”, “Customer Service” 和“Product Service”。
先說讀數(shù)據(jù),假設(shè)要創(chuàng)建一個“Order”,在這個過程中需要讀取“Customer”的數(shù)據(jù)和“Product”數(shù)據(jù)。
如果用事件通知的方式就只能在“Order Service”本地也創(chuàng)建只讀“Customer”和“Product”表,并把數(shù)據(jù)用消息的方式同步過來。
再說寫數(shù)據(jù),如果在創(chuàng)建一個“Order”時需要創(chuàng)建一個新的“Customer”或要修改“Customer”的信息,那么可以在界面上跳轉(zhuǎn)到用戶創(chuàng)建頁面,然后在“Customer Service”創(chuàng)建用戶之后再發(fā)”用戶已創(chuàng)建“的消息,“Order Service”接到消息,更新本地“Customer”表。
這并不是一個很好的使用事件驅(qū)動的例子,因為事件驅(qū)動的優(yōu)點就是不同的程序之間可以獨立運行,沒有綁定關(guān)系。但現(xiàn)在“Order Service”需要等待“Customer Service”創(chuàng)建完了之后才能繼續(xù)運行,來完成整個創(chuàng)建“Order”的工作。主要是因為“Order”和“Customer”本身從邏輯上來講就是緊耦合關(guān)系,沒有“Customer”你是不能創(chuàng)建“Order”的。
在這種緊耦合的情況下,也可以使用RPC。你可以建立一個更高層級的管理程序來管理這些微服務(wù)之間的調(diào)用,這樣“Order Service”就不必直接調(diào)用“Customer Service”了。
當(dāng)然它從本質(zhì)上來講并沒有解除耦合,只是把耦合轉(zhuǎn)移到了上一層,但至少現(xiàn)在“order Service”和“Customer Service”可以互不影響了。之所以不能根除這種緊耦合關(guān)系是因為它們在業(yè)務(wù)上是緊耦合的。
再舉一個購物的例子。用戶選好商品之后進行“Checkout”,生成“Order”,然后需要“payment”,再從“Inventory”取貨,最后由“Shipment”發(fā)貨,它們每一個都是微服務(wù)。這個例子用RPC方式和事件通知方式都可以完成。
當(dāng)用RPC方式時,由“Order”服務(wù)調(diào)用其他幾個服務(wù)來完成整個功能。用事件通知方式時,“Checkout”服務(wù)完成之后發(fā)送“Order Placed”消息,“Payment”服務(wù)收到消息,接收用戶付款,發(fā)送“Payment received”消息。
“Inventory”服務(wù)收到消息,從倉庫里取貨,并發(fā)送“Goods fetched”消息?!癝hipment”服務(wù)得到消息,發(fā)送貨物,并發(fā)送“Goods shipped”消息。
對這個例子來講,使用事件驅(qū)動是一個不錯的選擇,因為每個服務(wù)發(fā)消息之后它不需要任何反饋,這個消息由下一個模塊接收來完成下一步動作,時間上的要求也比上一個要寬松。用事件驅(qū)動的好處是降低了耦合度,壞處是你現(xiàn)在不能在程序里找到整個購物過程的步驟。
如果一個業(yè)務(wù)邏輯有它自己相對固定的流程和步驟,那么使用RPC或業(yè)務(wù)流程管理(BPM)能夠更方便地管理這些流程。在這種情況下選哪種方案呢?在我看來好處和壞處是大致相當(dāng)?shù)?。從技術(shù)上來講要選事件驅(qū)動,從業(yè)務(wù)上來講要選RPC。不過現(xiàn)在越來越多的人采用事件通知作為微服務(wù)的集成方式,它似乎已經(jīng)成了微服務(wù)之間的標椎調(diào)用方式。
事件溯源(Event Sourcing)
這是一種具有顛覆性質(zhì)的的設(shè)計,它把系統(tǒng)中所有的數(shù)據(jù)都以事件(Event)的方式記錄下來,它的持久存儲叫Event Store, 一般是建立在數(shù)據(jù)庫或消息隊列(例如Kafka)基礎(chǔ)之上,并提供了對事件進行操作的接口,例如事件的讀寫和查詢。事件溯源是由領(lǐng)域驅(qū)動設(shè)計(Domain-Driven Design)提出來的。
DDD中有一個很重要的概念,有界上下文(Bounded Context),可以用有界上下文來劃分微服務(wù),每個有界上下文都可以是一個微服務(wù)。下面是有界上下文的示例。下圖中有兩個服務(wù)“Sales”和“Support”。
有界上下文的一個關(guān)鍵是如何處理共享成員, 在圖中是“Customer”和“Product”。在不同的有界上下文中,共享成員的含義、用法以及他們的對象屬性都會有些不同,DDD建議這些共享成員在各自的有界上下文中都分別建自己的類(包括數(shù)據(jù)庫表),而不是共享??梢酝ㄟ^數(shù)據(jù)同步的手段來保持數(shù)據(jù)的一致性。下面還會詳細講解。
事件溯源是微服務(wù)的一種存儲方式,它是微服務(wù)的內(nèi)部實現(xiàn)細節(jié)。因此你可以決定哪些微服務(wù)采用事件溯源方式,哪些不采用,而不必所有的服務(wù)都變成事件溯源的。通常整個應(yīng)用程序只有一個Event Store, 不同的微服務(wù)都通過向Event Store發(fā)送和接受消息而互相通信。
Event Store內(nèi)部可以分成不同的stream(相當(dāng)于消息隊列中的Topic), 供不同的微服務(wù)中的領(lǐng)域?qū)嶓w(Domain Entity)使用。
事件溯源的一個短板是數(shù)據(jù)查詢,它有兩種方式來解決。第一種是直接對stream進行查詢,這只適合stream比較小并且查詢比較簡單的情況。
查詢復(fù)雜的話,就要采用第二種方式,那就是建立一個只讀數(shù)據(jù)庫,把需要的數(shù)據(jù)放在庫中進行查詢。數(shù)據(jù)庫中的數(shù)據(jù)通過監(jiān)聽Event Store中相關(guān)的事件來更新。
數(shù)據(jù)庫存儲方式只能保存當(dāng)前狀態(tài),而事件溯源則存儲了所有的歷史狀態(tài),因而能根據(jù)需要回放到歷史上任何一點的狀態(tài),具有很大優(yōu)勢。但它也不是一點問題都沒有。
第一,它的程序比較復(fù)雜,因為事件是一等公民,你必須把業(yè)務(wù)邏輯按照事件的方式整理出來,然后用事件來驅(qū)動程序。第二,如果你要想修改事件或事件的格式就比較麻煩,因為舊的事件已經(jīng)存儲在Event Store里了(事件就像日志,是只讀的),沒有辦法再改。
由于事件溯源和事件通知表面上看起來很像,不少人都搞不清楚它們的區(qū)別。事件通知只是微服務(wù)的集成方式,程序內(nèi)部是不使用事件溯源的,內(nèi)部實現(xiàn)仍然是傳統(tǒng)的數(shù)據(jù)庫方式。
只有當(dāng)要與其他微服務(wù)集成時才會發(fā)消息。而在事件溯源中,事件是一等公民,可以不要數(shù)據(jù)庫,全部數(shù)據(jù)都是按照事件的方式存儲的。
雖然事件溯源的踐行者有不同的意見,但有不少人都認為事件溯源不是微服務(wù)的集成方式,而是微服務(wù)的一種內(nèi)部實現(xiàn)方式。因此,在一個系統(tǒng)中,可以某些微服務(wù)用事件溯源,另外一些微服務(wù)用數(shù)據(jù)庫。
當(dāng)你要集成這些微服務(wù)時,你可以用事件通知的方式。注意現(xiàn)在有兩種不同的事件需要區(qū)分開,一種是微服務(wù)的內(nèi)部事件,是顆粒度比較細的,這種事件只發(fā)送到這個微服務(wù)的stream中,只被事件溯源使用。
另一種是其他微服務(wù)也關(guān)心的,是顆粒度比較粗的,這種事件會放到另外一個或幾個stream中,被多個微服務(wù)使用,是用來做服務(wù)之間集成的。這樣做的好處是限制了事件的作用范圍,減少了不相關(guān)事件對程序的干擾。詳見"Domain Events vs. Event Sourcing"。
事件溯源出現(xiàn)已經(jīng)很長時間了,雖然熱度一直在上升(尤其是這兩年),但總的來說非常緩慢,談?wù)摰娜瞬簧?,但生產(chǎn)環(huán)境使用的不多。究其原因就是應(yīng)為它對現(xiàn)在的體系結(jié)構(gòu)顛覆太大,需要更改數(shù)據(jù)存儲結(jié)構(gòu)和程序的工作方式,還是有一定風(fēng)險的。
另外,微服務(wù)已經(jīng)形成了一整套體系,從程序部署,服務(wù)發(fā)現(xiàn)與注冊,到監(jiān)控,服務(wù)韌性(Service Resilience),它們基本上都是針對RPC的,雖然也支持消息,但成熟度就差多了,因此有不少工作還是要自己來做。
有意思的是Kafka一直在推動它作為事件驅(qū)動的工具,也取得了很大的成功。但它卻沒有得到事件溯源圈內(nèi)的認可。
多數(shù)事件溯源都使用一個叫evenstore的開源Event Store,或是基于某個數(shù)據(jù)庫的Event Store,只有比較少的人用Kafka做Event Store。
但如果用Kafka實現(xiàn)事件通知就一點問題都沒有??偟膩碚f,對大多數(shù)公司來講事件溯源是有一定挑戰(zhàn)的,應(yīng)用時需要找到合適的場景。如果你要嘗試的話,可以先拿一個微服務(wù)試水。
雖然現(xiàn)在事件驅(qū)動還有些生澀,但從長遠來講,還是很看好它的。像其他全新的技術(shù)一樣,事件溯源需要大規(guī)模的適用場景來推動。例如容器技術(shù)就是因為微服務(wù)的流行和推動,才走向主流。
事件溯源以前的適用場景只限于記賬和源代碼庫,局限性較大。區(qū)塊鏈可能會成為它的下一個機遇,因為它用的也是事件溯源技術(shù)。
另外AI今后會滲入到具體程序中,使程序具有學(xué)習(xí)功能。而RPC模式注定沒有自適應(yīng)功能。事件驅(qū)動本身就具有對事件進行反應(yīng)的能力,這是自我學(xué)習(xí)的基礎(chǔ)。因此,這項技術(shù)長遠來講定會大放異彩,但短期內(nèi)(3-5年)大概不會成為主流。
RPC方式
RPC的方式就是遠程函數(shù)調(diào)用,像RESTFul,gRPC, DUBBO 都是這種方式。它一般是同步的,可以馬上得到結(jié)果。在實際中,大多數(shù)應(yīng)用都要求立刻得到結(jié)果,這時同步方式更有優(yōu)勢,代碼也更簡單。
服務(wù)網(wǎng)關(guān)(API Gateway)
熟悉微服務(wù)的人可能都知道服務(wù)網(wǎng)關(guān)(API Gateway)。當(dāng)UI需要調(diào)用很多微服務(wù)時,它需要了解每個服務(wù)的接口,這個工作量很大。
于是就用服務(wù)網(wǎng)關(guān)創(chuàng)建了一個Facade,把幾個微服務(wù)封裝起來,這樣UI就只調(diào)用服務(wù)網(wǎng)關(guān)就可以了,不需要去對付每一個微服務(wù)。下面是API Gateway示例圖:
服務(wù)網(wǎng)關(guān)(API Gateway)不是為了解決微服務(wù)之間調(diào)用的緊耦合問題,它主要是為了簡化客戶端的工作。其實它還可以用來降低函數(shù)之間的耦合度。
有了API Gateway之后,一旦服務(wù)接口修改,你可能只需要修改API Gateway, 而不必修改每個調(diào)用這個函數(shù)的客戶端,這樣就減少了程序的耦合性。
服務(wù)調(diào)用
可以借鑒API Gateway的思路來減少RPC調(diào)用的耦合度,例如把多個微服務(wù)組織起來形成一個完整功能的服務(wù)組合,并對外提供統(tǒng)一的服務(wù)接口。這種想法跟上面的API Gateway有些相似,都是把服務(wù)集中起來提供粗顆粒(Coarse Granular)服務(wù),而不是細顆粒的服務(wù)(Fine Granular)。
但這樣建立的服務(wù)組合可能只適合一個程序使用,沒有多少共享價值。因此如果有合適的場景就采用,否側(cè)也不必強求。雖然我們不能降低RPC服務(wù)之間的耦合度,卻可以減少這種緊耦合帶來的影響。
降低緊耦合的影響
什么是緊耦合的主要問題呢?就是客戶端和服務(wù)端的升級不同步。服務(wù)端總是先升級,客戶端可能有很多,如果要求它們同時升級是不現(xiàn)實的。它們有各自的部署時間表,一般都會選擇在下一次部署時順帶升級。
一般有兩個辦法可以解決這個問題:
同時支持多個版本:這個工作量比較大,因此大多數(shù)公司都不會采用這種方式。
服務(wù)端向后兼容:這是更通用的方式。例如你要加一個新功能或有些客戶要求給原來的函數(shù)增加一個新的參數(shù),但別的客戶不需要這個參數(shù)。這時你只好新建一個函數(shù),跟原來的功能差不多,只是多了一個參數(shù)。這樣新舊客戶的需求都能滿足。它的好處是向后兼容(當(dāng)然這取決于你使用的協(xié)議)。
它的壞處是當(dāng)以后新的客戶來了,看到兩個差不多的函數(shù)就糊涂了,不知道該用那個。而且時間越長越嚴重,你的服務(wù)端可能功能增加的不多,但相似的函數(shù)卻越來越多,無法選擇。
它的解決辦法就是使用一個支持向后兼容的RPC協(xié)議,現(xiàn)在最好的就是Protobuf gRPC,尤其是在向后兼容上。
它給每個服務(wù)定義了一個接口,這個接口是與編程語言無關(guān)的中性接口,然后你可以用工具生成各個語言的實現(xiàn)代碼,供不同語言使用。函數(shù)定義的變量都有編號,變量可以是可選類型的,這樣就比較好地解決了函數(shù)兼容的問題。
就用上面的例子,當(dāng)你要增加一個可選參數(shù)時,你就定義一個新的可選變量。由于它是可選的,原來的客戶端不需要提供這個參數(shù),因此不需要修改程序。
而新的客戶端可以提供這個參數(shù)。你只要在服務(wù)端能同時處理這兩種情況就行了。這樣服務(wù)端并沒有增加新的函數(shù),但用戶的新需求滿足了,而且還是向后兼容的。
微服務(wù)的數(shù)量有沒有上限?
總的來說微服務(wù)的數(shù)量不要太多,不然會有比較重的運維負擔(dān)。有一點需要明確的是微服務(wù)的流行不是因為技術(shù)上的創(chuàng)新,而是為了滿足管理上的需要。單體程序大了之后,各個模塊的部署時間要求不同,對服務(wù)器的優(yōu)化要求也不同,而且團隊人數(shù)眾多,很難協(xié)調(diào)管理。
把程序拆分成微服務(wù)之后,每個團隊負責(zé)幾個服務(wù),就容易管理了,而且每個團隊也可以按照自己的節(jié)奏進行創(chuàng)新,但它給運維帶來了巨大的麻煩。所以在微服務(wù)剛出來時,我一直覺得它是一個退步,弊大于利。但由于管理上的問題沒有其他解決方案,只有硬著頭皮上了。
值得慶幸的是微服務(wù)帶來的麻煩都是可解的。直到后來,微服務(wù)建立了全套的自動化體系,從程序集成到部署,從全鏈路跟蹤到日志,以及服務(wù)檢測,服務(wù)發(fā)現(xiàn)和注冊,這樣才把微服務(wù)的工作量降了下來。
雖然微服務(wù)在技術(shù)上一無是處,但它的流行還是大大推動了容器技術(shù),服務(wù)網(wǎng)格(Service Mesh)和全鏈路跟蹤等新技術(shù)的發(fā)展。不過它本身在技術(shù)上還是沒有發(fā)現(xiàn)任何優(yōu)勢。
直到有一天,我意識到單體程序其實性能調(diào)試是很困難的(很難分離出瓶頸點),而微服務(wù)配置了全鏈路跟蹤之后,能很快找到癥結(jié)所在。看來微服務(wù)從技術(shù)來講也不全是缺點,總算也有好的地方。但微服務(wù)的顆粒度不宜過細,否則工作量還是太大。
一般規(guī)模的公司十幾個或幾十個微服務(wù)都是可以承受的,但如果有幾百個甚至上千個,那么絕不是一般公司可以管理的。盡管現(xiàn)有的工具已經(jīng)很齊全了,而且與微服務(wù)有關(guān)的整個流程也已經(jīng)基本上全部自動化了,但它還是會增加很多工作。
Martin Fowler幾年以前建議先從單體程序開始(詳見 MonolithFirst),然后再逐步把功能拆分出去,變成一個個的微服務(wù)。但是后來有人反對這個建議,他也有些松口了。
如果單體程序不是太大,這是個好主意。可以用數(shù)據(jù)額庫表的數(shù)量來衡量程序的大小,我見過大的單體程序有幾百張表,這就太多了,很難管理。正常情況下,一個微服務(wù)可以有兩、三張表到五、六張表,一般不超過十張表。但如果要減少微服務(wù)數(shù)量的話,可以把這個標準放寬到不要超過二十張表。
用這個做為大致的指標來創(chuàng)建微程序,如果使用一段時間之后還是覺得太大了,那么再逐漸拆分。當(dāng)然,按照這個標準建立的服務(wù)更像是服務(wù)組合,而不是單個的微服務(wù)。不過它會為你減少工作量。只要不影響業(yè)務(wù)部門的創(chuàng)新進度,這是一個不錯的方案。
到底應(yīng)不應(yīng)該選擇微服務(wù)呢?如果單體程序已經(jīng)沒法管理了,那么你別無選擇。如果沒有管理上的問題,那么微服務(wù)帶給你的只有問題和麻煩。其實,一般公司都沒有太多選擇,只能采用微服務(wù),不過你可以選擇建立比較少的微服務(wù)。如果還是沒法決定,有一個折中的方案,“內(nèi)部微服務(wù)設(shè)計”。
內(nèi)部微服務(wù)設(shè)計
這種設(shè)計表面上看起來是一個單體程序,它只有一個源代碼存儲倉庫,一個數(shù)據(jù)庫,一個部署,但在程序內(nèi)部可以按照微服務(wù)的思想來進行設(shè)計。它可以分成多個模塊,每個模塊是一個微服務(wù),可以由不同的團隊管理。
用這張圖做例子。這個圖里的每個圓角方塊大致是一個微服務(wù),但我們可以把它作為一個單體程序來設(shè)計,內(nèi)部有五個微服務(wù)。
每個模塊都有自己的數(shù)據(jù)庫表,它們都在一個數(shù)據(jù)庫中,但模塊之間不能跨數(shù)據(jù)庫訪問(不要建立模塊之間數(shù)據(jù)庫表的外鍵)。
“User”(在Conference Management模塊中)是一個共享的類,但在不同的模塊中的名字不同,含義和用法也不同,成員也不一樣(例如,在“Customer Service”里叫“Customer”)。
DDD(Domain-Driven Design)建議不要共享這個類,而是在每一個有界上下文(模塊)中都建一個新類,并擁有新的名字。
雖然它們的數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)該大致相同,但DDD建議每一個有界上下文中都建一個新表,它們之間再進行數(shù)據(jù)同步。
這個所謂的“內(nèi)部微服務(wù)設(shè)計”其實就是DDD,但當(dāng)時還沒有微服務(wù),因此外表看起來是單體程序,但內(nèi)部已經(jīng)是微服務(wù)的設(shè)計了。
它的書在2003就出版了,當(dāng)時就很有名。但它更偏重于業(yè)務(wù)邏輯的設(shè)計,踐行起來也比較困難,因此大家談?wù)摰煤芏?,真正用的較少。
直到十年之后,微服務(wù)出來之后,人們發(fā)現(xiàn)它其實內(nèi)部就是微服務(wù),而且微服務(wù)的設(shè)計需要用它的思想來指導(dǎo),于是就又重新煥發(fā)了青春,而且這次更猛,已經(jīng)到了每個談?wù)撐⒎?wù)的人都不得不談?wù)揇DD的地步。不過一本軟件書籍,在十年之后還能指導(dǎo)新技術(shù)的設(shè)計,非常令人欽佩。
這樣設(shè)計的好處是它是一個單體程序,省去了多個微服務(wù)帶來的部署、運維的麻煩。但它內(nèi)部是按微服務(wù)設(shè)計的,如果以后要拆分成微服務(wù)會比較容易。至于什么時候拆分不是一個技術(shù)問題。
如果負責(zé)這個單體程序的各個團隊之間不能在部署時間表,服務(wù)器優(yōu)化等方面達成一致,那么就需要拆分了。
當(dāng)然你也要應(yīng)對隨之而來的各種運維麻煩。內(nèi)部微服務(wù)設(shè)計是一個折中的方案,如果你想試水微服務(wù),但又不愿意冒太大風(fēng)險時,這是一個不錯的選擇。
結(jié)論
微服務(wù)之間的調(diào)用有兩種方式,RPC和事件驅(qū)動。事件驅(qū)動是更好的方式,因為它是松耦合的。但如果業(yè)務(wù)邏輯是緊耦合的,RPC方式也是可行的(它的好處是代碼更簡單),而且你還可以通過選取合適的協(xié)議(Protobuf gRPC)來降低這種緊耦合帶來的危害。
由于事件溯源和事件通知的相似性,很多人把兩者弄混了,但它們實際上是完全不同的東西。微服務(wù)的數(shù)量不宜太多,可以先創(chuàng)建比較大的微服務(wù)(更像是服務(wù)組合)。
如果你還是不能確定是否采用微服務(wù)架構(gòu),可以先從“內(nèi)部微服務(wù)設(shè)計”開始,再逐漸拆分。
-
耦合
+關(guān)注
關(guān)注
13文章
582瀏覽量
100879 -
RPC
+關(guān)注
關(guān)注
0文章
111瀏覽量
11537 -
程序
+關(guān)注
關(guān)注
117文章
3787瀏覽量
81060
原文標題:微服務(wù)之間的最佳調(diào)用方式
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論