Informal Essay By English
I’m sorry that I haven’t updated the article lately because the blogger has been busy with interviews and summarizing their experience. I will create a special article to describe the recent events. Next, let’s get to the topic!
參考書籍:
- “鳳凰架構(gòu)”
- “微服務(wù)架構(gòu)設(shè)計模式”
引言
以往的文章中我們介紹了微服務(wù)架構(gòu)中遠(yuǎn)程服務(wù)調(diào)用中的兩種實(shí)現(xiàn)方式?;谝酝奈恼碌膶W(xué)習(xí)我們再深入思考一個問題“遠(yuǎn)程服務(wù)調(diào)用的目的是干什么?”這里博主先賣一個關(guān)子(注:會在本文的最后進(jìn)行回答),在此之前,讓我們介紹一下本文的核心內(nèi)容“微服務(wù)之異步消息通信”,看到這個標(biāo)題,有經(jīng)驗(yàn)的開發(fā)人員腦子里面就已經(jīng)蹦出了兩個詞“MQ”,對的就是目前討論話題熱度一直處于比較高的一個中間件。本文不會去重點(diǎn)說某一個消息中間件,而是會從消息機(jī)制的角度去解釋MQ的特性。本文將討論討論以下幾個主題,包括在擴(kuò)展接收方的同時保持消息的順序、檢測和丟棄重復(fù)的消息,以及作為數(shù)據(jù)庫事務(wù)的一部分發(fā)送和接收消息。讓我們從查看消息機(jī)制的工作原理開始
什么是消息傳遞
Gregor Hope 和 Bobby Woolf 在《Enterprise Integration Patterns 》一書
中 定 義 了一 種 有 用 的 消 息 傳 遞 模 型 。在這個模型里面,消息實(shí)體是通過消息通道進(jìn)行交換的。發(fā)送方(應(yīng)用程序或服務(wù))將消息寫入通道,接收方(應(yīng)用程序或服務(wù))從通道讀取消息。
消息
消息由標(biāo)頭(標(biāo)識或安全信息等元數(shù)據(jù))和主體組成。其中標(biāo)頭是名稱和值對的集合,描述正在發(fā)送的數(shù)據(jù)的元數(shù)據(jù)。除了消息發(fā)送者提供的名稱與值對之外,消息頭部還包含其他信息,例如發(fā)件人或消息傳遞基礎(chǔ)設(shè)施生成的唯一消息D,以及可選的返回地址,該地址指定發(fā)送回復(fù)的消息通道。消息正文是以文本或二進(jìn)制格式發(fā)送的數(shù)據(jù)。
將消息歸類可以劃分為以下幾種類型:
-
文檔:僅包含數(shù)據(jù)的通用消息。由消息接收者去決定怎么消費(fèi)。對命令式消息的回復(fù)是文檔消息的一種使用場景
-
命令:一條等同于RPC請求的消息。它指定要調(diào)用的操作及其參數(shù)
-
事件:表示發(fā)送方這一端發(fā)生了重要的事件。事件通常是領(lǐng)域事件,表示領(lǐng)域?qū)ο?(如 o r d e r 或 C u s t o m e r )的狀態(tài)更改
消息通道
如下圖所示,消息通過消息通道進(jìn)行交換。發(fā)送方中的業(yè)務(wù)邏輯調(diào)用發(fā)送端接口,該接口封裝底層通信機(jī)制。 發(fā)送端由消息發(fā)送適配器類實(shí)現(xiàn)(六邊形架構(gòu)),該消息發(fā)送適配器類通過消息通道向接收器發(fā)送消息。消息通道是消息傳遞基礎(chǔ)設(shè)施的抽象。調(diào)用接收器中的消息處理程序適配器類來處理消息。它調(diào)用接收方業(yè)務(wù)邏輯實(shí)現(xiàn)的接收端接口。任意數(shù)量的發(fā)送方都可以向通道發(fā)送消息 。類似地,任何數(shù)量的接收方都可以從通道接收消息
消息通道可以分為“點(diǎn)對點(diǎn)”、“發(fā)布-訂閱”這兩種類型:
-
點(diǎn)對點(diǎn)通道:向正在從通道讀取的一個消費(fèi)者傳遞消息。服務(wù)使用點(diǎn)對點(diǎn)通道來實(shí)現(xiàn)一對一交互方式。例如,命令式消息通常通過點(diǎn)對點(diǎn)通道發(fā)送
-
發(fā)布-訂閱:通道將一條消息發(fā)給所有訂閱的接收方。服務(wù)使用發(fā)布一訂閱通道來實(shí)現(xiàn)一對多交互方式。例如,事件式消息通常通過發(fā)布一訂閱通道發(fā)送
使用消息機(jī)制實(shí)現(xiàn)交互方式
消息機(jī)制的一個有價值的特性是它足夠靈活,可以支持常見的如下圖所示的所有交互方式,下圖中的一些交互方式可以直接通過消息機(jī)制直接實(shí)現(xiàn)。其他的必須在消息機(jī)制之上實(shí)現(xiàn)。
我們來看看消息是如何來實(shí)現(xiàn)上圖的交互方式的,先從請求/響應(yīng)和異步請求/響應(yīng)開始
實(shí)現(xiàn)請求 / 響應(yīng)和異步請求 / 響應(yīng)
當(dāng)客戶端和服務(wù)使用請求/ 響應(yīng) 或異步請求/ 響應(yīng)進(jìn)行交互時,客戶端會發(fā)送請求,服務(wù)會發(fā)回回復(fù)。兩種交互方式之間的區(qū)別在于,對于請求/ 響應(yīng),客戶端期望服務(wù)立即響應(yīng),而對于異步請求/ 響應(yīng),則沒有這樣的期望。消息機(jī)制本質(zhì)上是異步的,因此只提供異步請求/ 響應(yīng)。但客戶端可能會堵塞,直到收到回復(fù)。
客戶端和服務(wù)端通過交換 一對消息來實(shí)現(xiàn)異步請求/響應(yīng)方式的交互。如下圖所示, 客戶端發(fā)送命令式消息,該消息指定要對服務(wù)執(zhí)行的操作和參數(shù),這些內(nèi)容通過服務(wù)擁有的 點(diǎn)對點(diǎn)消息通道傳遞。該服務(wù)處理請求,并將包含結(jié)果的回復(fù)消息發(fā)送到客戶端擁有的點(diǎn)對點(diǎn)通道
客戶端必須告知服務(wù)發(fā)送回復(fù)消息的位置,并且必須將回復(fù)消息與請求匹配。幸運(yùn)的是,解決這兩個問題并不困難??蛻舳税l(fā)送具有回復(fù)通道頭部的命令式消息。服務(wù)器將回復(fù)消息寫人回復(fù)通道,該回復(fù)消息包含與消息標(biāo)識符具有相同值的相關(guān)性ID??蛻舳耸褂孟嚓P(guān)性 ID將回復(fù)消息與請求進(jìn)行匹配。
由于客戶端和服務(wù)使用消息機(jī)制進(jìn)行通信,因此交互本質(zhì)上是異步的。理論上,使用消息機(jī)制的客戶端可能會阻塞,直到收到回復(fù),但實(shí)際上客戶端將異步處理回復(fù)。而且,回復(fù)通常可以由任何一個客戶端實(shí)例處理。
實(shí)現(xiàn)單向通知
使用異步消息實(shí)現(xiàn)單向通知非常簡單。客戶端將消息( 通常是命令式消息)發(fā)送到服務(wù)所擁有的點(diǎn)對點(diǎn)通道。服務(wù)訂閱該通道并處理該消息,但是服務(wù)不會發(fā)回回復(fù)。
實(shí)現(xiàn)發(fā)布 / 訂閱
消息機(jī)制內(nèi)置了對發(fā)布/ 訂網(wǎng)交互方式的支持??蛻舳藢⑾l(fā)布到由多個接收方讀取的發(fā)布/ 訂閱通道,發(fā)布領(lǐng)域事件的服務(wù)擁有自己的發(fā)布/ 訂閱通道,通道的名稱往往派生自領(lǐng)域類。例如,Google Cloud Pub/Sub提供競爭消費(fèi)者和發(fā)布訂閱頻道語義,通過主題(發(fā)布訂閱)和訂閱(競爭消費(fèi)者)進(jìn)行管理,如下圖所示,在本例中,訂閱方Y(jié)和訂閱方Z都在訂閱同一主題C時接收消息3的副本,但要通過單獨(dú)的訂閱。Google Cloud Pub/Sub不支持通配符訂閱
實(shí)現(xiàn)發(fā)布/異步響應(yīng)
發(fā)布/ 異步響應(yīng)交互方式是一種更高級別的交互方式,它通過把發(fā)布/ 訂閱和請求/ 響應(yīng) 這兩種方式的元素組合在一起實(shí)現(xiàn)??蛻舳税l(fā)布一條消息,在消息的頭部中指定回復(fù)通道, 這個通道同時也是一個發(fā)布一訂閱通道。消費(fèi)者將包含相關(guān)性D的回復(fù)消息寫人回復(fù)通道。 客戶端通過使用相關(guān)性1D來收集響應(yīng),以此將回復(fù)消息與請求進(jìn)行匹配。 應(yīng)用程序中包含異步API 的每個服務(wù)都會使用這些實(shí)現(xiàn)技術(shù)中的一種或多種。帶有異步 API調(diào)用操作的服務(wù)會擁有一個用于發(fā)出請求的通道 ,同樣地,需要發(fā)布事件的服務(wù)也會擁有一個事件式消息發(fā)布通道。
為基于消息機(jī)制的服務(wù)API創(chuàng)建API規(guī)范(Application Programming Interface:應(yīng)用程序編程接口)
服務(wù)的異步API 規(guī)范必須指定消息通道的名稱、通過每個通道交換的消息類型及其格式。你還必須使用諸如JSON、XML或Protobuf 之類的標(biāo)準(zhǔn)來描述消息的格式。 但與REST 和Open API 不同,并沒有廣泛采用的標(biāo)準(zhǔn)來記錄通道和消息類型,你需要自己編寫這樣的文檔。
服務(wù)的異步API 包含供客戶端調(diào)用的操作和由服務(wù)對外發(fā)布的事件 。這些API 的記錄方式不盡相同。讓我們從操作開始逐一分析。
記錄異步操作
- 請求/ 異步響應(yīng)式API :包括服務(wù)的命令消息通道、服務(wù)接受的命令式消息的具體類型和格式,以及服務(wù)發(fā)送的回復(fù)消息的類型和格式
- 單向通知式 API:包括服務(wù)的命令消息通道,以及服務(wù)接受的命令式消息的具體類型和格式。
需要注意的是服務(wù)可以對異步請求/ 響應(yīng)和單向通知使用相同的請求通道。
記錄事件發(fā)布
服務(wù)還可以使用發(fā)布/ 訂閱的方式對外發(fā)布事件。此API 風(fēng)格的規(guī)范包括事件通道以及服務(wù)發(fā)布到通道的事件式消息的類型和格式。
消息和消息通道模型是一種很好的抽象,也是設(shè)計服務(wù)異步API 的好方法。但是,為了實(shí)現(xiàn)服務(wù),你需要選擇具體的消息傳遞技術(shù)并確定如何使用它們的能力來實(shí)現(xiàn)設(shè)計。讓我們看一看所涉及的內(nèi)容
使用消息代理
基于消息傳遞的應(yīng)用程序通常使用消息代理,即服務(wù)通信的基礎(chǔ)設(shè)施服務(wù)。但基于消息 代理的架構(gòu)并不是唯一的消息架構(gòu)。你還可以使用基于無代理的消息傳遞架構(gòu),其中服務(wù)直接相互通信。這兩種方法(如下圖所示)具有不同的利弊,但通常基于代理的架構(gòu)是一種更好的方法
我們先看第一種“無代理架構(gòu)”的實(shí)現(xiàn)方式:
無代理消息
所謂的無代理其實(shí)就是不引入一個新的角色進(jìn)行消息轉(zhuǎn)發(fā),而是由需要通過消息專遞信息的兩臺服務(wù)器直接交互。ZeroMQ 是一種流行的無代理消息技術(shù)。它既是規(guī)范,也是一組適用于不同編程語言的庫。它支持各種傳輸協(xié)議, 包括TCP、UNIX風(fēng)格的套接字和多播。
使用無代理架構(gòu)有以下好處:
- 允許更輕的網(wǎng)絡(luò)流量和更低的延遲,因?yàn)橄⒅苯訌陌l(fā)送方發(fā)送到接收方,而不必從發(fā)送方到消息代理,再從代理轉(zhuǎn)發(fā)到接收方
- 消除了消息代理可能成為性能瓶頸或單點(diǎn)故障的可能性
- 具有較低的操作復(fù)雜性,因?yàn)椴恍枰O(shè)置和維護(hù)消息代理
同樣的無代理也有著非常明顯的弊端:
- 服務(wù)需要了解彼此的位置,因此必須使用服務(wù)發(fā)現(xiàn)機(jī)制
- 會導(dǎo)致可用性降低,因?yàn)樵诮粨Q消息時,消息的發(fā)送方和接收方都必須同時在線
- 在實(shí)現(xiàn)例如確保消息能夠成功投遞這些復(fù)雜功能時的挑戰(zhàn)性更大
無代理架構(gòu)中的一些弊端于使用同步請求/響應(yīng)交互方式所導(dǎo)致的弊端相同,因此很多時候我們都會選用基于消息代理的架構(gòu)。
基于代理的消息
這種基于代理的消息其實(shí)就是我們目前市面上流傳的MQ,如:Apache ActiveMQ、RabbitMQ、Apache Kafka、RocketMQ(以前由阿里維護(hù),現(xiàn)交由apache維護(hù))
這種架構(gòu)的消息的一個重要好處是發(fā)送方不需要知道接收方的網(wǎng)絡(luò)位置。另一個好處是消息代理緩沖消息,直到接收方能夠處理它們
在進(jìn)行MQ的技術(shù)棧的選擇的時候我們需要關(guān)注一下幾個點(diǎn):
- 支持的編程語言:你選擇的消息代理應(yīng)該支持盡可能多的編程語言
- 支持的消息標(biāo)準(zhǔn):消息代理是否支持多種消息標(biāo)準(zhǔn),比如AMQP 和STOMP,還是它僅支持專用的消息標(biāo)準(zhǔn)
- 消息排序:消息代理是否能夠保留消息的排序
- 投遞保證:消息代理提供什么樣的消息投遞保證
- 持久性:消息是否持久化保存到磁盤并且能夠在代理崩潰時恢復(fù)
- 耐久性:如果接收方重新連接到消息代理,它是否會收到斷開連接時發(fā)送的消息
- 可擴(kuò)展性:消息代理的可擴(kuò)展性如何
- 延遲:端到端是否有較大延遲
- 并發(fā):消息代理是否支持高并發(fā)場景
每個消息代理都有不同的側(cè)重點(diǎn)。例如,一個非常低延遲的代理可能不會保留消息的順序 ,不保證消息投遞成功,只在內(nèi)存中存儲消息。保證投遞成功并在磁盤上可靠地存儲消息的代理可能具有更高的延遲。哪種消息代理最適合取決于你的應(yīng)用程序的需求。你的應(yīng)用程序的不同部分甚至可能具有不同的消息傳遞需求。 但是,消息順序和可擴(kuò)展性很可能是必不可少的。
還是同樣的,先列舉一下使用代理架構(gòu)的消息的優(yōu)勢:
- 松耩合:客戶端發(fā)起請求時只要發(fā)送給特定的通道即可,客戶端完全不需要感知服務(wù)實(shí)例的情況,客戶端不需要使用服務(wù)發(fā)現(xiàn)機(jī)制去獲得服務(wù)實(shí)例的網(wǎng)絡(luò)位置
- 消息緩存:消息代理可以在消息被處理之前一直緩存消息。像HTTP這樣的同步請求/ 響應(yīng)協(xié)議 ,在交換數(shù)據(jù)時,發(fā)送方和接收方必領(lǐng)同時在線。然而,在使用消息機(jī)制的情況下,消息會在隊(duì)列中緩存,直到它們被按收方處理。這就意味著,例如,即使訂單處理系統(tǒng)暫時離線或不可用,在線商店仍1舊能夠接受客戶的訂單。訂單消息將會在隊(duì)列中緩存 (并不會丟失)
- 靈活的通信:消息機(jī)制支持前面提到的所有交互方式
- 明確的進(jìn)程間通信:基于RPC的機(jī)制總是企圖讓遠(yuǎn)程服務(wù)調(diào)用跟本地調(diào)用看上去沒
什么區(qū)別 (在客戶端和服務(wù)端同時使用遠(yuǎn)程調(diào)用代理)。然而,因?yàn)槲锢矶?(如服務(wù)器不可預(yù)計的硬件失效)和可能的局部故障,遠(yuǎn)程和本地調(diào)用還是大相徑庭的。消息機(jī)制讓這些差異變得很明確,這樣軟件工程師不會陷人一種“太平盛世” 的錯覺
有優(yōu)勢必然會有一定弊端,使用代理架構(gòu)的消息有如下弊端:
- 潛在的性能瓶頸:消息代理可能存在性能瓶頸(許多現(xiàn)代消息代理都支持高度的橫向擴(kuò)展)
- 潛在的單點(diǎn)故障:消息代理的高可用性至關(guān)重要,否則系統(tǒng)整體的可靠性將受到影響(大多數(shù)現(xiàn)代消息代理都是高可用的)
- 額外的操作復(fù)雜性 :消息系統(tǒng)是一個必須獨(dú)立安裝、配置和運(yùn)維的系統(tǒng)組件(這個才是最主要的弊端??)
到此,基于消息的通信,我們已經(jīng)介紹的差不多了,其實(shí)在《微服務(wù)架構(gòu)設(shè)計模式》中還對目前主流的MQ中間件是如何“處理并發(fā)和消息順序”、“處理重復(fù)消息”、“事物性消息”這幾個點(diǎn)進(jìn)行了詳細(xì)的描述,但是博主認(rèn)為這些都是設(shè)計到具體的中間件的事情,不應(yīng)該放到這種偏理論的文章中,以后MQ專題中,我們可以單拎出來進(jìn)行一個詳細(xì)的解釋,因此此篇文章并不花篇幅去解釋了。
最后就是再回答一開始提出的問題“遠(yuǎn)程服務(wù)調(diào)用的目的是干什么?”文章來源:http://www.zghlxwxcb.cn/news/detail-450275.html
遠(yuǎn)程服務(wù)調(diào)用的本質(zhì)其實(shí)還是不同進(jìn)程間的消息傳遞,既然RPC的本質(zhì)是進(jìn)行消息傳遞,那么RPC能做的事情,MQ很大程度上也是可以做到的,那么為什么還要有這種兩技術(shù)棧出現(xiàn)讓我們開發(fā)人員去選擇呢?其實(shí)主要還是由他們在交互方式的實(shí)現(xiàn)上有不同,因此導(dǎo)致不同的業(yè)務(wù)場景需要使用不同的技術(shù)棧去實(shí)現(xiàn)不同進(jìn)程間的消息傳遞,稍微總結(jié)歸納一下就是:文章來源地址http://www.zghlxwxcb.cn/news/detail-450275.html
- 使用 RPC 的場景一般都是上游服務(wù)需要實(shí)時依賴下游服務(wù)的返回
- 使用MQ的場景一般都是上游不關(guān)心下游結(jié)果的場景
到了這里,關(guān)于微服務(wù)之異步消息通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!