开发中的坑:MQ 也能做 RPC 调用?
hi, 大家好,我是 haohongfan。
最近瀏覽 帖子[1] 的時(shí)候看到一個(gè)有意思的吐槽。
大概意思是架構(gòu)師沒有選用 RPC 框架來做服務(wù)間調(diào)用,而選擇用 MQ 來代替。是不是很意外?
當(dāng)然不出意外的,評(píng)論區(qū)炸了!
現(xiàn)在提出一些疑問:
這個(gè)架構(gòu)師的做法對(duì)嗎 ?
MQ 是否能做 RPC 調(diào)用 ?
RPC 框架的職責(zé)
回答上面問題之前,稍微捋一下 RPC 框架。目前市面上比較流行的 RPC 框架其實(shí)并不多。
Java: SpringCloud,Dubbo 等
Go: Dubbogo,go-micro,rpcx,go-zero 等
其他:Thrift,gRPC 等
當(dāng)然還有其他的一些框架,這里就不再羅列。雖說 RPC 多如牛毛,但是大家干的事情基本都差不多,都是穩(wěn)定,高效、準(zhǔn)確的進(jìn)行服務(wù)間遠(yuǎn)程調(diào)用。
說起 RPC 應(yīng)該大部分人下意識(shí)會(huì)聯(lián)想到 gRPC,不過 gRPC 只提供了服務(wù)間通信的能力,但卻沒有開源對(duì)應(yīng)的服務(wù)治理的能力,需要進(jìn)行二次開發(fā)。Thrift 也是同樣的問題。
下面以 Dubbogo 為例,大概介紹下 Dubbogo 實(shí)現(xiàn)的功能。
Dubbo-go 還有下面這些特點(diǎn):
傳輸支持 http2
雙向流模式 rpc
應(yīng)用級(jí)服務(wù)發(fā)現(xiàn)
跟 Dubbo(Java) 版本對(duì)齊,互相之間能穩(wěn)定通信,同時(shí)也打通與其他微服務(wù)框架的通信,如:SpringCloud、gRPC
綜上,Dubbo-go 為了保證數(shù)據(jù)準(zhǔn)確、高效、穩(wěn)定傳輸,做了各種各樣的架構(gòu)設(shè)計(jì)。隨著 dubbo 3.0 的發(fā)布,在易用性、超大規(guī)模微服務(wù)實(shí)踐、云原生基礎(chǔ)設(shè)施適配等幾大方向上進(jìn)行了全面升級(jí)。
MQ 代替 RPC ?
接著說 MQ 是否能替代 RPC。先看看 MQ 被寫進(jìn)八股文里面的幾大特性:
服務(wù)間解耦
最終一致性
流量削峰
異步消費(fèi)
MQ 是微服務(wù)框架中必不可少的一環(huán),上面的特性是我們?nèi)粘i_發(fā)中最常用的。這些特性確實(shí)能讓系統(tǒng)的穩(wěn)定性得到增強(qiáng),同時(shí)也讓系統(tǒng)的構(gòu)建出現(xiàn)更多的可能性。
但是是否能讓 MQ 來代替 RPC,做服務(wù)間的調(diào)用?回答這個(gè)問題之前,我們?cè)賮砜纯?RPC 是如何工作的。
大概流程(資料節(jié)選 dubbogo website[2])
類似本地調(diào)用,Client 調(diào)用遠(yuǎn)程服務(wù)
Client stub 收到調(diào)用,把調(diào)用方法、參數(shù)序列化
Client 通過 socket 把消息發(fā)送到服務(wù)端
Server stub 收到消息后,將消息對(duì)象反序列化
Server stub 根據(jù)解碼結(jié)果調(diào)用本地的服務(wù),并將結(jié)果返回給 Server stub
Server stub 將返回結(jié)果序列化,通過 sockets 將消息發(fā)送到客戶端
Client stub 接收到結(jié)果消息,對(duì)返回消息反序列化
客戶端得到最終結(jié)果
簡(jiǎn)單概括下 RPC 調(diào)用就是 Client 通過 TCP 調(diào)用 Server 的一個(gè)函數(shù),得到一個(gè)返回結(jié)果。
再簡(jiǎn)單點(diǎn),是不是可以拆分下面兩個(gè)過程:
Client 發(fā)起一個(gè)調(diào)用到 Server
Server 返回一個(gè)結(jié)果到 Client
那么是不是可以用 MQ 模擬這個(gè)過程。
當(dāng)然這個(gè)流程并不是我瞎寫的,這是 RabbitMQ 的官方教程 Remote procedure call (RPC)[3],有興趣的可以看文末的參考鏈接。
RabbitMQ tutorial 這篇文章基本就是 MQ 代替 RPC 的理論支持,所以文章開篇帖子提到的 Java 架構(gòu)師的方案也不算無的放矢,也不算是錯(cuò)的。
MQ 代替 RPC 的真實(shí)情況
正常情況有點(diǎn)規(guī)?;ヂ?lián)網(wǎng)公司內(nèi)部都是會(huì)有一套 RPC 框架的,要么是基于開源版本的二次開發(fā)版本,要么完全自研的,使用過或者維護(hù)公司框架的都會(huì)被各種問題折磨到死,比如:限流、熔斷、重試、服務(wù)注冊(cè)發(fā)現(xiàn)、網(wǎng)絡(luò)問題,SDK 升級(jí)等。
如果能用 MQ 代替 RPC 做服務(wù)間調(diào)用,那是不是只用維護(hù)一套 MQ 基礎(chǔ)組件就可以了,既減少了人力的配置,又能將問題歸納。
理想很豐滿,真相往往卻很殘酷。
如果你下意識(shí)去搜一下:用 MQ 代替 RPC 進(jìn)行服務(wù)間通信,你會(huì)發(fā)現(xiàn)網(wǎng)上只有寥寥幾個(gè) Demo 而已,并沒有太多真實(shí)實(shí)踐。
沒有太多實(shí)踐 并不代表沒有人在項(xiàng)目中實(shí)戰(zhàn)過,比如那個(gè) Java 架構(gòu)師。曾經(jīng)專門向朋友請(qǐng)教過這個(gè)設(shè)計(jì),話說某大廠曾經(jīng)在某個(gè)項(xiàng)目做了 MQ 代替 RPC 的實(shí)踐,但是三個(gè)月不到這個(gè)項(xiàng)目就被斃了。所以你看不到這個(gè)設(shè)計(jì)方案的缺點(diǎn):因?yàn)楹芏嗳瞬荒馨咽〉陌咐懦鰜矶选?/p>
簡(jiǎn)單說下這個(gè)方案的缺點(diǎn)吧:
本來 一次 TCP 通信就搞定的事情,用 MQ 后會(huì)被拆分成?四次 TCP,耗時(shí)增加不少。
目前 MQ 大部分消費(fèi)端是 Pull 模型,有一定的耗時(shí)成本
服務(wù)間調(diào)用完全依賴于 MQ 的穩(wěn)定性。從目前使用 MQ 經(jīng)驗(yàn)來看,MQ 穩(wěn)定性的維護(hù)成本比 RPC 復(fù)雜太多了。如果做異步調(diào)用還能容忍出錯(cuò)、延時(shí),做同步調(diào)用的話,這些都是不能忽略的問題
如果用 MQ 代替 RPC,那些 RPC 框架做的服務(wù)治理的事情,MQ 都需要實(shí)現(xiàn)一遍,工作量并沒有減少
。。。
現(xiàn)在說一下統(tǒng)一結(jié)論:
用 MQ 代替 RPC 只是一種理論,但是高可用無法保障,而且對(duì)業(yè)務(wù)開發(fā)來說就更加黑盒了,出現(xiàn)問題就只能干瞪眼了,不建議業(yè)務(wù)開發(fā)實(shí)踐。
更多的坑,后續(xù)更新,歡迎關(guān)注公眾號(hào)。更多學(xué)習(xí)學(xué)習(xí)資料分享,關(guān)注公眾號(hào):
參考資料
[1]
帖子: https://www.toutiao.com/w/a1702697615869956/
[2]dubbogo website: https://dubbo.apache.org/zh/blog/2019/01/07/%E6%B5%85%E8%B0%88-rpc/
[3]Remote procedure call (RPC): https://www.rabbitmq.com/tutorials/tutorial-six-python.html
總結(jié)
以上是生活随笔為你收集整理的开发中的坑:MQ 也能做 RPC 调用?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是 Go runtime.KeepA
- 下一篇: 如何有效控制 Go 线程数?