構(gòu)建微服務(wù)之:微服務(wù)架構(gòu)中的進(jìn)程間通信

原文鏈接:Building Microservices: Inter-Process Communication in a Microservices Architecture

  1. 微服務(wù)介紹
  2. 構(gòu)建微服務(wù)之使用API網(wǎng)關(guān)
  3. 構(gòu)建微服務(wù)之:微服務(wù)架構(gòu)中的進(jìn)程間通信(本文)
  4. 微服務(wù)中的服務(wù)發(fā)現(xiàn)
  5. 微服務(wù)之事件驅(qū)動(dòng)的數(shù)據(jù)管理
  6. 選擇一種微服務(wù)部署策略
  7. 重構(gòu)單體應(yīng)用到微服務(wù)

這是使用微服務(wù)架構(gòu)構(gòu)建應(yīng)用系列的第三篇文章。第一篇文章介紹了微服務(wù)架構(gòu)模式并討論了使用微服務(wù)的優(yōu)勢和劣勢 ;第二篇文章介紹了應(yīng)用的客戶端如何通過API網(wǎng)關(guān)作為中介實(shí)現(xiàn)服務(wù)間的通信;在這篇文章中我們將看一看同一系統(tǒng)間的服務(wù)如何通信;第四篇文章主要介紹服務(wù)發(fā)現(xiàn)的問題。

介紹

在傳統(tǒng)單體應(yīng)用中,模塊間使用編程語言級(jí)別的方法或功能彼此調(diào)用。然而微服務(wù)架構(gòu)應(yīng)用本質(zhì)上是運(yùn)行在多臺(tái)機(jī)器上的分布式系統(tǒng),每個(gè)服務(wù)都是一個(gè)進(jìn)程!因此,下圖為我們展示,微服務(wù)必須使用進(jìn)程間通信(IPC)的機(jī)制實(shí)現(xiàn)交互:

Paste_Image.png

稍后,我們將看具體的 IPC 技術(shù)實(shí)現(xiàn),但首先讓我們探討不同方案設(shè)計(jì)中的問題。

交互風(fēng)格

當(dāng)我們?yōu)榉?wù)選擇一種IPC機(jī)制的時(shí)候,我們首先要考慮服務(wù)間如何交互,技術(shù)上存在多種 client?service 交互風(fēng)格:它們可以按照兩大維度分類:第一維度是服務(wù)間交互是一對(duì)一還是一對(duì)多;

  • 一對(duì)一:每個(gè)客戶端請(qǐng)求只會(huì)被一個(gè)服務(wù)實(shí)例處理。
  • 一對(duì)多:每個(gè)請(qǐng)求將會(huì)被多個(gè)服務(wù)實(shí)例處理

第二個(gè)維度是交互是同步模式還是異步模式:

  • 同步:客戶端期望來自服務(wù)端的及時(shí)響應(yīng),甚至可能阻塞并等待。
  • 異步:客戶端等待響應(yīng)時(shí)不會(huì)阻塞,對(duì)異步來講,及時(shí)響應(yīng)并不是必須的。

下列表格展示了兩種方式的不同

一對(duì)一 一對(duì)多
同步 請(qǐng)求/響應(yīng)
異步 通知 發(fā)布/訂閱
異步 請(qǐng)求/異步響應(yīng) 發(fā)布/異步響應(yīng)

有下面幾種一對(duì)一的交互方式:

  • 請(qǐng)求/響應(yīng)模式: 客戶端向服務(wù)端發(fā)送請(qǐng)求并等待響應(yīng),并期望服務(wù)端可以及時(shí)的返回響應(yīng)。在一個(gè)基于線程的應(yīng)用中,發(fā)出請(qǐng)求的線程可能在等待時(shí)阻塞線程的執(zhí)行。
  • 通知(也就是單向請(qǐng)求):客戶端往服務(wù)端發(fā)送請(qǐng)求,但并不等待響應(yīng)返回
  • 請(qǐng)求/異步響應(yīng):客戶端往一個(gè)異步返回響應(yīng)的服務(wù)發(fā)送請(qǐng)求。客戶端等待式并不會(huì)阻塞線程,因?yàn)樵O(shè)計(jì)時(shí)就假設(shè)請(qǐng)求不會(huì)立即返回(js回調(diào))

有下面幾種一對(duì)多的交互方式:

  • 發(fā)布/訂閱模式:客戶端發(fā)布一個(gè)通知消息,消息將會(huì)被0或多個(gè)感興趣的服務(wù)消費(fèi)
  • 發(fā)布/異步響應(yīng):客戶端發(fā)布一個(gè)請(qǐng)求消息,并在一定時(shí)間內(nèi)等待消費(fèi)消息的服務(wù)響應(yīng)。

每個(gè)服務(wù)通常會(huì)使用多種交互風(fēng)格的組合:對(duì)一些服務(wù)來講,簡單的IPC機(jī)制可能已經(jīng)足夠了,但另外一些服務(wù)可能需要幾種IPC機(jī)制的組合。下圖展示了在taxi-hailing應(yīng)用中,當(dāng)用戶請(qǐng)求行程時(shí),服務(wù)是如何交互的:

Paste_Image.png

這個(gè)服務(wù)使用了通知、請(qǐng)求/響應(yīng)、發(fā)布/訂閱風(fēng)格的組合。比如,乘客使用智能手機(jī)向行程管理服務(wù)發(fā)送一個(gè)接送需求的通知,行程管理服務(wù)將使用請(qǐng)求/響應(yīng)模式調(diào)用乘客服務(wù)來驗(yàn)證乘客賬號(hào)是否為活動(dòng)狀態(tài),然后行程管理服務(wù)創(chuàng)建行程并使用發(fā)布/訂閱方式來通知諸如分發(fā)器(用來定位空閑司機(jī))等服務(wù)。

我們已經(jīng)討論了交互風(fēng)格,那么再來看下如何定義API。

定義API

服務(wù)API是服務(wù)與客戶之間的契約。拋開選擇哪種IPC機(jī)制的選擇,使用一些接口定義語言interface definition language (IDL)準(zhǔn)確定義服務(wù)API是很重要的!.當(dāng)然,最好考慮使用API優(yōu)先的方式來定義服務(wù),通過先寫接口定義語言來開始開發(fā),并與客戶端開發(fā)者(服務(wù)消費(fèi)者)一起review你的設(shè)計(jì),先對(duì)API定義進(jìn)行迭代,再去實(shí)現(xiàn)這些服務(wù)。這樣做設(shè)計(jì)的話將會(huì)使你構(gòu)建更加符合客戶需求的服務(wù)!

后續(xù)文章你將會(huì)發(fā)現(xiàn),服務(wù)定義和你選擇哪種IPC機(jī)制息息相關(guān),如果你是要消息機(jī)制,API就由消息頻道和消息類型組成;如果你使用http,API就是由URLs以及request/response格式組成。稍后我們將會(huì)討論更多關(guān)于接口定義語言的細(xì)節(jié)。

API進(jìn)化

服務(wù)API將會(huì)不可避免的隨著時(shí)間進(jìn)化,在傳統(tǒng)單體應(yīng)用中,我們可以很直接的去修改服務(wù)并更新所有服務(wù)的調(diào)用者(refactor)。但是在基于微服務(wù)架構(gòu)的應(yīng)用中,哪怕服務(wù)API的其他消費(fèi)者都是在一個(gè)應(yīng)用中,去更新所有服務(wù)也是相當(dāng)困難的。你通常不能強(qiáng)制讓所有的客戶端升級(jí)來保持和服務(wù)端升級(jí)維持步調(diào)一致,而且,你還可能會(huì)增量部署新服務(wù)使得新老服務(wù)同時(shí)運(yùn)行,尋找一種處理此種情況的策略是很重要的。

你是如何根據(jù)更改的大小來處理服務(wù)API的變化的呢?一些變化很小,通常可以與之前版本做到向后兼容,比如,你為請(qǐng)求或相應(yīng)添加了一個(gè)屬性;對(duì)此,設(shè)計(jì)服務(wù)時(shí)考慮服務(wù)和客戶消費(fèi)者的魯棒性原則是很有必要的:使用就版本服務(wù)API的客戶端可以在新版本服務(wù)API下正常工作,服務(wù)端為客戶端缺失的屬性提供默認(rèn)值,客戶端自動(dòng)忽略額外添加的響應(yīng)屬性。最后強(qiáng)調(diào),注意使用IPC機(jī)制和定義消息格式使你的API可以簡單方便的進(jìn)化!

當(dāng)然,有時(shí)候我們不得不對(duì)API做一些較大的,不再兼容的變化,而我們這時(shí)候又不可能強(qiáng)制每個(gè)客戶端升級(jí),因此我們的服務(wù)就要繼續(xù)支持運(yùn)行一段時(shí)間的老版本API。如果使用http,我們可以在URL里嵌入服務(wù)版本,每個(gè)服務(wù)實(shí)例可能同時(shí)處理多個(gè)版本的服務(wù),當(dāng)然,你也可以選擇為每個(gè)服務(wù)版本部署單獨(dú)的服務(wù)實(shí)例。

處理局部故障

就像前面關(guān)于API網(wǎng)關(guān)文章提到的那樣:在分布式系統(tǒng)中總會(huì)有無時(shí)無刻的局部故障的風(fēng)險(xiǎn)。由于客戶端和服務(wù)在不同的進(jìn)程中,服務(wù)可能由于掛掉或者維護(hù)原因而不能及時(shí)響應(yīng)客戶端的請(qǐng)求,或者服務(wù)由于過載原因?qū)е马憫?yīng)緩慢。

比如,讓我們考慮之前文章提到的Product details場景,假設(shè)推薦服務(wù)沒有響應(yīng)了,一個(gè)簡單的客戶端實(shí)現(xiàn)可能無期限的等待服務(wù)響應(yīng)并阻塞,這樣不僅導(dǎo)致糟糕的用戶體驗(yàn),在很多應(yīng)用中還會(huì)消耗比如線程這樣寶貴的資源,最終就像下圖展示的那樣,運(yùn)行時(shí)將會(huì)用盡所有線程使得服務(wù)不再響應(yīng)任何請(qǐng)求:

Paste_Image.png

為解決此類問題,設(shè)計(jì)上處理局部故障是很有必要的。

Netflix給出了一些處理局部故障比較好的方法:

  • 網(wǎng)絡(luò)超時(shí):等待響應(yīng)時(shí)不要一直阻塞,而是使用超時(shí),超時(shí)能夠保證資源不會(huì)一直被占用
  • 限制未完成請(qǐng)求的數(shù)量:針對(duì)一個(gè)請(qǐng)求某服務(wù)的客戶端,需要設(shè)置其未處理請(qǐng)求數(shù)量的上限,一旦超過限制就不再處理任何請(qǐng)求,這樣就做到快速失敗。
  • 斷路器模式:跟蹤成功和失敗請(qǐng)求的數(shù)量,如果比率超過了設(shè)置的閥值,打開斷路器使得后續(xù)請(qǐng)求快速失敗。如果大量請(qǐng)求失敗,就建議服務(wù)為不可以狀態(tài)并決絕處理新請(qǐng)求,過一段時(shí)間之后,客戶端可以再次重試,一旦成功,關(guān)閉斷路器。
  • 提供fallback機(jī)制:請(qǐng)求失敗時(shí)提供fallback,比如返回緩存值或者為失敗的推薦服務(wù)返回默認(rèn)空集合作為默認(rèn)值。
    Netflix Hystrix是一個(gè)實(shí)現(xiàn)了這些模式的開源工具包,如果你使用JVM那么一定要考慮使用它!如果你的服務(wù)不是運(yùn)行在JVM中,那也要考慮有等效的實(shí)現(xiàn)來處理此類問題。

IPC 技術(shù)

我們有不同的IPC技術(shù)可供選擇:服務(wù)可以使用基于請(qǐng)求/響應(yīng)的同步通信模式,比如基于Http的REST或者Thrift,當(dāng)然,也可以使用異步基于消息的通信模式,比如AMQP、STOMP。這些通信模式有不同的消息格式,服務(wù)可以使用基于文本格式、方便閱讀的JSON 或者 XML格式,也可以使用效率更高的二進(jìn)制格式(比如Avro或Protocol Buffers)。稍后我們將討論同步IPC機(jī)制,現(xiàn)在我們先討論下異步的IPC機(jī)制:

異步,基于消息的通信

使用消息時(shí),進(jìn)程間通過異步交換消息來通信。一個(gè)客戶端通過發(fā)送消息的方式請(qǐng)求服務(wù),如果期望服務(wù)有響應(yīng),也是服務(wù)通過向客戶端發(fā)送另外的消息來實(shí)現(xiàn)。由于通信是異步的,客戶端不會(huì)為了響應(yīng)等待并阻塞,相反的,客戶端編程時(shí)就是以服務(wù)不會(huì)立即返回響應(yīng)來處理的。

一條消息包含消息頭(元數(shù)據(jù)和發(fā)送者)和消息體,消息通過頻道進(jìn)行交換,任意數(shù)量的消費(fèi)者都可以往頻道中發(fā)消息,任意數(shù)量的消費(fèi)者也可以消費(fèi)頻道中的消息。有point?to?pointpublish?subscribe兩種頻道:point?to?point模式下,頻道的消息只會(huì)被交付到某一個(gè)消費(fèi)者,這種模式用于前面提到的一對(duì)一的交互;publish?subscribe 模式下,頻道的消息將會(huì)交付到所有感興趣的消費(fèi)者,使用于前面提到的一對(duì)多交互風(fēng)格。

下圖展示了taxi-hailing 應(yīng)用可能是一publish-subscribe模式:

Paste_Image.png

行程管理服務(wù)通過向publish-subscribe頻道寫入trip create消息的方式通知比如分發(fā)器這樣感興趣的服務(wù),分發(fā)器查找空閑司機(jī)并通過向publish-subscribe頻道寫入Driver Proposed消息通知其他服務(wù)。

有多種消息系統(tǒng)供我們選擇,當(dāng)然我們盡量選擇一個(gè)支持多種編程語言的來使用。一些消息系統(tǒng)支持標(biāo)準(zhǔn)的協(xié)議比如 AMQP和STOMP,另一些消息系統(tǒng)有專有但是文檔化的協(xié)議,大量的開源消息系統(tǒng)可供我們挑選,包括RabbitMQ、Apache Kafka、Apache ActiveMQ和NSQ。統(tǒng)一的來看,他們都支持某種形式的消息和頻道,都致力于高可靠,高性能和高擴(kuò)展性,但是每個(gè)消息中介在實(shí)現(xiàn)細(xì)節(jié)上還是有很大的不同:
使用消息系統(tǒng)有很多優(yōu)點(diǎn):

  • 客戶端與服務(wù)端解耦: 客戶端只需要向合適的頻道發(fā)送消息就實(shí)現(xiàn)簡單的請(qǐng)求,客戶端完全感知不到服務(wù)實(shí)例的存在,因此不需要再去使用一套服務(wù)發(fā)現(xiàn)機(jī)制去決定服務(wù)實(shí)例的位置。
  • 緩存消息:在同步的請(qǐng)求/響應(yīng)協(xié)議,比如HTTP下,客戶端和服務(wù)端在交互的階段必須保證雙方都可用,然而,消息中介會(huì)把消息寫入隊(duì)列直到消息被消費(fèi)者處理位置,這意味著,盡管 在訂單履行系統(tǒng)響應(yīng)緩慢甚至不可用情況下,在線商城仍然可以接受來自客戶的訂單,只需要先把訂單消息簡單的入隊(duì)即可。
  • 靈活的客戶-服務(wù)端交換風(fēng)格,消息支持前面提到的所有交互風(fēng)格。
  • 顯示的進(jìn)程間通信:基于 RPC的通信機(jī)制試圖使調(diào)用遠(yuǎn)程服務(wù)等同于調(diào)用本地服務(wù)。然而,由于物理定律和局部故障的可能性,事實(shí)上他們相當(dāng)不同。消息使這些差異非常明顯,因此開發(fā)人員不被虛假的安全感所迷惑。

當(dāng)然消息系統(tǒng)也有缺點(diǎn):

  • 額外的運(yùn)維復(fù)雜度:消息系統(tǒng)畢竟也是額外的系統(tǒng)組件,也要求安裝、配置、運(yùn)維等操作,有必要保證消息系統(tǒng)的高可用,否則會(huì)影響整個(gè)系統(tǒng)的穩(wěn)定性。
  • 實(shí)現(xiàn)請(qǐng)求/響應(yīng)交互的復(fù)雜度:要實(shí)現(xiàn)請(qǐng)求/響應(yīng)的交互風(fēng)格還是要做些額外工作的:每條請(qǐng)求消息必要要包含回復(fù)頻道的標(biāo)志符以及關(guān)聯(lián)標(biāo)志符 ,服務(wù)回寫包含關(guān)聯(lián)ID的消息到回復(fù)頻道,客戶端使用關(guān)聯(lián)ID去匹配請(qǐng)求對(duì)應(yīng)的響應(yīng)。當(dāng)然,如果使用直接支持請(qǐng)求/響應(yīng)的基于IPC機(jī)制的方式,將會(huì)特別簡單。

我們已經(jīng)討論了基于消息的IPC,再看檢驗(yàn)下基于請(qǐng)求/響應(yīng)的IPC吧:

同步,基于請(qǐng)求/響應(yīng)的IPC

當(dāng)使用同步,基于請(qǐng)求/響應(yīng)的IPC機(jī)制的時(shí)候,客戶端向服務(wù)端發(fā)送請(qǐng)求,服務(wù)端處理請(qǐng)求并返回響應(yīng),很多客戶端,發(fā)出請(qǐng)求的線程會(huì)在等待響應(yīng)過程中阻塞,另外有一些客戶端也會(huì)使用異步、事件驅(qū)動(dòng)的代碼,比如封裝好的Futures 或 Rx Observables。然而,和使用消息不一樣,客戶端假設(shè)請(qǐng)求會(huì)立即返回。有幾種方案供我們選擇,比較流行就是REST和 Thrift,我們先看下REST:

REST

限制使用REST風(fēng)格暴露API很流行,REST基本就是使用HTTP的IPC 機(jī)制,REST的關(guān)鍵理念是資源,也就是通常代表諸如用戶或產(chǎn)品的某個(gè)或一組業(yè)務(wù)對(duì)象,REST使用HTTP verbs維護(hù)URL指向的資源,比如 GET返回某資源的表示,可能是XML也可能是JSON對(duì)象, POST會(huì)創(chuàng)建新資源,PUT更新資源··· 引用自Roy Fielding,提出REST的大牛:

“REST provides a set of architectural constraints that, when applied as a whole, emphasizes scalability of component interactions, generality of interfaces, independent deployment of components, and intermediary components to reduce interaction latency, enforce security, and encapsulate legacy systems.”
—Fielding, Architectural Styles and the Design of Network-based Software Architectures

下圖展示了**taxi-hailing **應(yīng)用使用REST的場景:


Paste_Image.png

乘客向行程服務(wù)/trips發(fā)送POST請(qǐng)求,行程服務(wù)通過向乘客管理服務(wù)發(fā)送GET請(qǐng)求獲取乘客信息,在驗(yàn)證完乘客授權(quán)之后,創(chuàng)建行程,行程服務(wù)創(chuàng)建行程后返回201響應(yīng)給手機(jī).

很多用了HTTP暴露服務(wù)API的開發(fā)就說自己是REST,其實(shí)按照 Fielding 在blog post描述的規(guī)定,他們根本不是REST。 Leonard Richardson (no relation)定義了非常有用的 maturity model for REST組成了下面幾個(gè)級(jí)別:

  • Level 0 :客戶端使用HTTP POST調(diào)用服務(wù)固定的URL,每次請(qǐng)求指定動(dòng)作和參數(shù)
  • Level 1:支持資源的概念,請(qǐng)求通過POST,并且要制定要做的動(dòng)作和參數(shù)
  • Level 2:充分使用 HTTP verbs 執(zhí)行動(dòng)作GET獲取資源 POST創(chuàng)建資源PUT更新資源,還是要請(qǐng)求參數(shù)和請(qǐng)求體,還可以指定請(qǐng)求的參數(shù),使得服務(wù)充分使用web基礎(chǔ)架構(gòu)的功能,比如緩存請(qǐng)求等
  • Level 3: API定義按照HATEOAS (Hypertext As The Engine Of Application State) 原則。基本的定義就是GET請(qǐng)求返回表示資源的body中包含一些對(duì)資源允許動(dòng)作的鏈接。比如,客戶端可以使用get訂單返回的訂單body中的一個(gè)超鏈接取消一個(gè)訂單。HATEOAS 優(yōu)點(diǎn)之一是:客戶端不用在代碼中硬編碼URL了,另外,由于返回的body中包含允許對(duì)資源所作動(dòng)作的超鏈接,客戶端就不需要再猜測當(dāng)前資源狀態(tài)下他可以做哪些操作了。

使用基于HTTP的協(xié)議的優(yōu)點(diǎn)有:

  • HTTP 簡單而且大家都熟悉
  • 可以用瀏覽器測試,配合比如Postman插件更佳,命令行curl也很方便(假設(shè)使用json或其他數(shù)據(jù)格式)
  • 直接就支持請(qǐng)求/響應(yīng)風(fēng)格的通信
  • HTTP很友好
  • 無需中介,簡化架構(gòu)

使用HTTP的缺點(diǎn):

  • HTTP只支持請(qǐng)求/響應(yīng)風(fēng)格的交互,你可以使用HTTP請(qǐng)求向服務(wù)器發(fā)送通知,但是服務(wù)器一定要返回HTTP響應(yīng)。
  • 客戶端和服務(wù)端沒有消息buffer機(jī)制,交互都是直接的,這就要求交換消息的時(shí)候雙方必須同時(shí)運(yùn)行。
  • 客戶端必須知道每個(gè)服務(wù)實(shí)例的地址,比如URL,正如前面的API網(wǎng)關(guān)文章描述的那樣,在現(xiàn)代流行的應(yīng)用架構(gòu)中,這已經(jīng)不再是一個(gè)問題,我們可以使用服務(wù)發(fā)現(xiàn)機(jī)制來定位服務(wù)實(shí)例。

開發(fā)者論壇最近又重新發(fā)掘了RESTful API風(fēng)格接口定義語言的價(jià)值,我們可以選擇使用RAML或者Swagger等工具, Swagger允許定義請(qǐng)求響應(yīng)的消息格式,RAML則要求你使用額外的諸如JSON Schema這樣的定義.IDL除了描述API,通常還會(huì)提供根據(jù)接口定義生產(chǎn)客戶端Stub或服務(wù)端骨架的工具。

Thrift

Apache Thrift是REST的一個(gè)很有意思的替代品,它是一個(gè)實(shí)現(xiàn)跨語言客戶端與服務(wù)端RPC通信的框架。Thrift提供C語言風(fēng)格的接口定義語言來定義API,你可以通過編譯生成客戶端Stub和服務(wù)端的骨架,編譯器可以為 C++、Java、Python、PHP、Ruby、Erlang、Node.js等不同語言生產(chǎn)代碼。

一個(gè)Thrift接口包含一個(gè)或多個(gè)服務(wù),一個(gè)服務(wù)定義可以類比java的接口:都是一組強(qiáng)類型方法的集合。Thrift方法可以返回值也可以被定義為單向通信,如果方法需要返回值就需要實(shí)現(xiàn)請(qǐng)求/響應(yīng)風(fēng)格的交互,客戶端等待響應(yīng)的時(shí)候可能會(huì)拋出異常;單向通信就是我們前面講到的通知風(fēng)格的交互,服務(wù)端不需要返回響應(yīng)。

Thrift支持不同的消息格式:JSON、binary以及compact binary。 Binary相對(duì)JSON更加高效,因?yàn)榻獯a速度更快,compact binary比JSON空間利用率高,見名知意嘛,JSON則對(duì)人和瀏覽器更加的友好 ;Thrift也支持不同的通信協(xié)議選擇:原生TCP或者HTTP,原生TCP相比HTTP肯定更加高效,但是HTTP對(duì)防火墻、人以及瀏覽器更加的友好。

消息格式

既然我們已經(jīng)討論了HTTP和Thrift,現(xiàn)在再來探討下消息格式的問題吧:如果你需要消息系統(tǒng)或者REST風(fēng)格交互,你就必須選擇消息格式。其他類似Thrift的IPC機(jī)制可能只支持一小部分的消息格式,甚至只會(huì)支持一種!在某些情況下,使用一種支持跨語言的消息格式非常重要,哪怕你現(xiàn)在只有一種語言實(shí)現(xiàn)微服務(wù),誰又能保證你以后不會(huì)使用新的語言呢?

主要有文本和二進(jìn)制兩種格式:文本格式包括JSON和XML等,文本格式不僅僅方便閱讀,而且是自描述的,JOSN中對(duì)象屬性是采用一組鍵值對(duì)的組合來表示的;同樣,XML的屬性是采用命名元素和值來表示的,這樣允許消費(fèi)者只挑選感興趣的消息摒棄其他消息,因而這種方式也可以方便的做到向后兼容。

XML文檔的結(jié)構(gòu)是由XML schema來指定的,隨著時(shí)間的流逝,開發(fā)者論壇逐步意識(shí)到JSON也需要類似的機(jī)制:一種選擇是使用JSON Schema,要么單獨(dú)使用,要么作為類似Swagger這種IDL的一部分使用。

文本格式消息的缺點(diǎn)是非常的冗長,尤其是XML格式:由于消息是自描述的,每條消息除了值之外還包含屬性的名稱,另一個(gè)缺點(diǎn)就是解析文本開銷略大,這時(shí)候可以考慮下二進(jìn)制格式。

二進(jìn)制格式也有多種選擇:如果使用Thrift,你可以選擇Thrift binary,如果選擇其他的消息格式,比較流行的還有Protocol Buffers和Apache Avro,兩種格式都提供了IDL來定義消息的結(jié)構(gòu)。區(qū)別是,Protocol Buffers使用標(biāo)記字段,而Avro 消費(fèi)者則需要了解Schema才能解析消息,因此使用Protocol Buffers時(shí),API進(jìn)化比Avro更容易。這篇 文章是一個(gè)對(duì)Thrift、 Protocol Buffers以及 Avro非常好的比較。

總結(jié)

微服務(wù)需要使用進(jìn)程間通信的機(jī)制進(jìn)行交互,當(dāng)設(shè)計(jì)你的服務(wù)如何通信的時(shí)候,需要考慮多個(gè)問題:服務(wù)如何交互、如何為服務(wù)定義API、如何處理API進(jìn)化、如何處理局部故障。有兩種微服務(wù)可以使用的IPC機(jī)制:異步消息和同步的請(qǐng)求/響應(yīng)。該系列的下一篇文章,將會(huì)講解微服務(wù)架構(gòu)中的服務(wù)發(fā)現(xiàn)問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容