03.02 任務隊列,消息隊列和rpc的區別是什麼?

小卷奧特曼


說實話,第一次看到這個問題,真心有點兒暈。在工作中,任務隊列,消息隊列和rpc都是常用的實踐方案,但是這三者解決的問題似乎沒有什麼相關性。如:任務隊列往往是需要大規模處理業務邏輯時,將相關的任務入隊列,進行異步調用,從而解決任務阻塞的問題;消息隊列是異構系統(或者說系統)之間異步通信的一種方法,主要是用來解決系統間信息同步問題的;而rpc是一種遠程調用方式,是在代碼的實現層面異步調用外部服務用的。就這種描述來看,三者之間的確沒有什麼瓜葛。

但是出於好奇,我在網上搜索了這個問題,發現知乎有相同的問題,並且有大神【靈劍】給出了比較專業的答案,我將其答案描述如下。

任務隊列、消息隊列、rpc是不同層次上的東西,任務隊列是邏輯模型,消息隊列是通信模型,RPC是包含了通信模型的編程模型(或者框架)。

消息隊列(MQ)是一種能實現生產者到消費者單向通信的通信模型,一般來說是指實現這個模型的中間件,比如RabbitMQ。它可以是一個產品,或者是操作系統提供的一種服務之類。

RPC一般來說是具體指某一種RPC編程框架或協議,如JSON-RPC、GRPC等,它自己有一整套通信的規範,而在此之上實現什麼功能是可以定製的。對於RPC來說,調用方不太關心底層的通信機制,只關心它能實現遠程調用這一點;框架則不太關心上面承載的究竟是怎樣的應用,只負責將調用過程發送到執行端,並將結果回傳。

任務隊列則是個邏輯上的概念,即將抽象的任務發送到執行的worker的組件,有的時候包含了後端的worker,有的時候不包含,並沒有什麼具體的形式,也沒有什麼規範。

這三者並沒有特別大的聯繫,但也不一定是完全不同的東西,比如說RPC可以通過MQ來實現,而任務隊列可以通過MQ實現,也可以利用RPC實現,底層可能都是相同的東西,但是因為暴露出了不同性質的接口所以也換了不同的名字。以上的區分也不絕對,很多情況下只是怎麼方便就怎麼叫。

任務隊列是邏輯模型,消息隊列是通信模型,RPC是包含了通信模型的編程模型(或者框架),概念清晰,很有概括性,這個答案值得讀,也值得了解和學習。尤其是底層的東西可能是相同的,但是封裝之後對於提供的接口和功能起不同的名字,更是軟件開發中的普遍現象。


夕陽雨晴


首先,這幾個概念本就不是同一層次上的東西,本身風馬牛不相及。

先說RPC

RPC通常指的是PRC框架(分佈式框架),或者PRC協議,如GRPC,JSON-RPC等。這類框架主要解決遠程通信間的問題,所以底層的通信機制是不需要使用者去關心去實現就能很好實現遠程通信的,最出名的莫過於阿里的dubbo。

再說任務隊列

這是個邏輯概念,即比如飯店高峰期時,顧客單子不得不按照下單順序一個個放在廚房,進行先後炒菜處理,這一堆的單子就是任務隊列。

最後說消息隊列

消息隊列(MQ)可以理解成兩個應用程序間(生產者消費者間)的通信,例如短信發送模塊,因為模塊的發送速度跟不上,這時候需要有一個容器,暫存一下,緩解下壓力,那麼“消息隊列”就是在消息的傳輸過程中保存消息的“容器”。然後短信模塊就可以從容不怕的去消息隊列取出要發出的短信內容,進行發送處理。


Java進階架構師


它們之間聯繫確實不緊密,非得區分的話。

(1)任務隊列和消息隊列是異步,RPC是同步處理。

(2)任務隊列是業務話術,而消息隊列和RPC是技術話術

RPC (遠程過程調用)簡單理解即把別人的系統當作自己的系統調用。

優點:

(1)引入別人的接口,把別人的系統當作自己的調用,調用方便

(2)一般是長連接,請求訪問效率高。

缺點:

(1)需引用被調用系統的接口包,調用的外部系統越多,本系統將越來越龐大,陷入泥球模式。

(2)編程語言有較大限制,一般只能調用當前語言的RPC。

(3)建立的是長連接,所以會消耗一定的系統資源。不同於http的即插即用。

具體實例:一般為webservice和dubbo。

消息隊列:即常用異步通訊技術,常見的有RabbitMQ, RocketMQ, ActiveMQ, Kafka

主要是通過生產消費者模式來實現兩者之間的通訊,幾者區別如下:

一般的業務場景異步我選擇RabbitMQ,在大量數據日誌處理我選擇kafka。

任務隊列,從本質上看是一個業務的概念。它觸發的方式可以是RPC,消息隊列,甚至可以是Http。

這是我的一點看法,若有其它觀點可以一起留言探討


閒浮半日


其實這個問題本身是有些問題的,任務隊列,消息隊列和 RPC 完全是幾個不相關的概念,或者說它們並不是同一層面的概念,如果非要扯上一些關係的話,那麼任務隊列可以通過消息隊列實現,RPC 和消息隊列是同步和異步的差別。


任務隊列

我還沒有聽說過一個叫做任務隊列的框架、中間件或其他任務和技術有關的名詞;我能想象到的任務隊列,更多的是一個業務概念,當有很多任務(硬件資源不足以同時處理這些任務),或任務和任務之間有先後順序的時候,可以通過對其進行排序處理,這就是任務隊列。


RPC

RPC:Remote Procedure Call,中文意思就是遠程過程調用。

遠程是相對於本地來說的,有遠程調用就有本地調用,那麼先說說本地調用是什麼,這個就簡單了;

比如下圖,我們的代碼在同一個進程中(或者說同一個地址空間)調用另外一個方法,得到我們需要的結果,這就是本地調用:

那麼想象一下,如果這裡的add方法是一個很複雜的方法,很多系統都想用這個方法,那麼我們可以把這個方法單獨拆成一個服務,提供給各個系統進行調用,那麼本地就會變成遠程,就會變成這樣:


那麼在 Server_A 中怎麼調用 Server_B 中的 add 方法呢?

很多人都會想到 Server_B 封裝一個接口,通過服務把這個方法暴露出去,比如通過 HTTP 請求,那麼 Server_A 就可以調用 Server_B 中的 add 方法了。

通過這種方法實現起來沒有問題,也是一個不錯的解決方法,就是在每次調用的時候,都要發起 HTTP 請求,代碼裡面要寫 HttpClient.sendRequest 這樣的代碼,那麼我們有沒有可能像調用本地一樣,去發起遠程調用呢?讓程序員不知道這是調用的遠程方法呢?這時候就要提到RPC了(並不是說 RPC 優於 HTTP 請求,關於這兩個概念我們在下文中討論)。

完整的RPC過程,如圖:

  • 服務調用方(Client)調用以本地調用方式調用服務;

  • Client stub 負責將方法名、參數組裝成消息體並進行序列化,找到服務地址,將消息發送到服務端;

  • Server stub 收到消息後進行反序列化後調用本地的服務;

  • 本地服務執行,將結果返回給 Server stub;

  • Server stub 將運行結果打包成消息序列化後,發送調用方;

  • Client stub接收到消息,並進行反序列化,調用方最終得到調用結果。

總結來說,RPC 用於服務之間的調用問題,特別是分佈式環境;RPC 讓遠程調用時,像調用本地方法一樣方便和無感知;RPC框架屏蔽了很多底層的細節,不需要開發人員關注這些細節,比如序列化和反序列化、網絡傳輸協議的細節。


消息隊列

在正式講解之前,讓我們看一個簡單的場景:

用戶支付成功後,發送一條提示短信;假設支付的時候會調用支付系統的接口,所需時間 X ms,發送短信會調用短信平臺的接口,所需時間 Y ms,那麼支付動作一共需要 (X + Y) ms ,如果 Y 值比較大的時候,會造成整個支付過程很慢,那麼我們有沒有更好的解決方案呢?


下面,讓我們帶著這個問題來了解一下什麼是消息隊列,以及消息隊列的使用場景。

我們可以把消息隊列看做是一個存放消息的容器,我們可以往這個容器中放入消息,也可以從這個容器中取出消息;放入消息的叫做生產者,取走消息的叫做消費者;

  • 點對點:如果生產者放入一條消息,只能被一個消費者取走一次,這叫做點對點模式;(point to point,queue);

  • 發佈/訂閱:如果生產者放入一條消息,可以被多個消費者取走,這叫做發佈/訂閱模式;(publish/subscribe,topic);

我覺得使用消息隊列主要有兩點好處:

1.異步解耦

如果A系統直接調用B系統的接口,那麼當B系統出現故障的時候,A系統也會受到影響;如果A和B之間不直接進行調用,那麼耦合度就會變得很低。

2.流量削鋒

還是A系統調用B系統的接口,還有另外一種場景,A發起的調用量在某個時間段突然增多,很可能導致B系統崩潰宕機;這時,A系統可以將請求發送到消息隊列中,B系統按照自己的處理能力,從消息隊列中訂閱消息進行處理,達到了流量削鋒的效果。

我們再回到上面的問題,是不是使用消息隊列就可以很好的解決這個問題了;給客戶發送短信這個業務場景,時效性要求並不高,所以完全可以在支付過程中,把通知短信發到消息隊列中,再由短信平臺消費信息發送短信。


總之,任務隊列,消息隊列和 RPC 三者的關係就在於:任務隊列可以通過消息隊列實現,RPC 和消息隊列是同步和異步的差別。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


分享到:


相關文章: