-
1 # Java進階架構師
-
2 # 夕陽雨晴
說實話,第一次看到這個問題,真心有點兒暈。在工作中,任務佇列,訊息佇列和rpc都是常用的實踐方案,但是這三者解決的問題似乎沒有什麼相關性。如:任務佇列往往是需要大規模處理業務邏輯時,將相關的任務入佇列,進行非同步呼叫,從而解決任務阻塞的問題;訊息佇列是異構系統(或者說系統)之間非同步通訊的一種方法,主要是用來解決系統間資訊同步問題的;而rpc是一種遠端呼叫方式,是在程式碼的實現層面非同步呼叫外部服務用的。就這種描述來看,三者之間的確沒有什麼瓜葛。
但是出於好奇,我在網上搜索了這個問題,發現知乎有相同的問題,並且有大神【靈劍】給出了比較專業的答案,我將其答案描述如下。
任務佇列、訊息佇列、rpc是不同層次上的東西,任務佇列是邏輯模型,訊息佇列是通訊模型,RPC是包含了通訊模型的程式設計模型(或者框架)。
訊息佇列(MQ)是一種能實現生產者到消費者單向通訊的通訊模型,一般來說是指實現這個模型的中介軟體,比如RabbitMQ。它可以是一個產品,或者是作業系統提供的一種服務之類。
RPC一般來說是具體指某一種RPC程式設計框架或協議,如JSON-RPC、GRPC等,它自己有一整套通訊的規範,而在此之上實現什麼功能是可以定製的。對於RPC來說,呼叫方不太關心底層的通訊機制,只關心它能實現遠端呼叫這一點;框架則不太關心上面承載的究竟是怎樣的應用,只負責將呼叫過程傳送到執行端,並將結果回傳。
任務佇列則是個邏輯上的概念,即將抽象的任務傳送到執行的worker的元件,有的時候包含了後端的worker,有的時候不包含,並沒有什麼具體的形式,也沒有什麼規範。
這三者並沒有特別大的聯絡,但也不一定是完全不同的東西,比如說RPC可以透過MQ來實現,而任務佇列可以透過MQ實現,也可以利用RPC實現,底層可能都是相同的東西,但是因為暴露出了不同性質的介面所以也換了不同的名字。以上的區分也不絕對,很多情況下只是怎麼方便就怎麼叫。
任務佇列是邏輯模型,訊息佇列是通訊模型,RPC是包含了通訊模型的程式設計模型(或者框架),概念清晰,很有概括性,這個答案值得讀,也值得了解和學習。尤其是底層的東西可能是相同的,但是封裝之後對於提供的介面和功能起不同的名字,更是軟體開發中的普遍現象。
-
3 # 閒浮半日
它們之間聯絡確實不緊密,非得區分的話。
(1)任務佇列和訊息佇列是非同步,RPC是同步處理。
(2)任務佇列是業務話術,而訊息佇列和RPC是技術話術
RPC (遠端過程呼叫)簡單理解即把別人的系統當作自己的系統呼叫。
優點:
(1)引入別人的介面,把別人的系統當作自己的呼叫,呼叫方便
(2)一般是長連線,請求訪問效率高。
缺點:
(1)需引用被呼叫系統的介面包,呼叫的外部系統越多,本系統將越來越龐大,陷入泥球模式。
(2)程式語言有較大限制,一般只能呼叫當前語言的RPC。
(3)建立的是長連線,所以會消耗一定的系統資源。不同於http的即插即用。
具體例項:一般為webservice和dubbo。
訊息佇列:即常用非同步通訊技術,常見的有RabbitMQ, RocketMQ, ActiveMQ, Kafka
主要是透過生產消費者模式來實現兩者之間的通訊,幾者區別如下:
一般的業務場景非同步我選擇RabbitMQ,在大量資料日誌處理我選擇kafka。
任務佇列,從本質上看是一個業務的概念。它觸發的方式可以是RPC,訊息佇列,甚至可以是Http。
-
4 # 會點程式碼的大叔
其實這個問題本身是有些問題的,任務佇列,訊息佇列和 RPC 完全是幾個不相關的概念,或者說它們並不是同一層面的概念,如果非要扯上一些關係的話,那麼任務佇列可以透過訊息佇列實現,RPC 和訊息佇列是同步和非同步的差別。
任務佇列我還沒有聽說過一個叫做任務佇列的框架、中介軟體或其他任務和技術有關的名詞;我能想象到的任務佇列,更多的是一個業務概念,當有很多工(硬體資源不足以同時處理這些任務),或任務和任務之間有先後順序的時候,可以透過對其進行排序處理,這就是任務佇列。
RPCRPC: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 和訊息佇列是同步和非同步的差別。
回覆列表
首先,這幾個概念本就不是同一層次上的東西,本身風馬牛不相及。
先說RPCRPC通常指的是PRC框架(分散式框架),或者PRC協議,如GRPC,JSON-RPC等。這類框架主要解決遠端通訊間的問題,所以底層的通訊機制是不需要使用者去關心去實現就能很好實現遠端通訊的,最出名的莫過於阿里的dubbo。
再說任務佇列這是個邏輯概念,即比如飯店高峰期時,顧客單子不得不按照下單順序一個個放在廚房,進行先後炒菜處理,這一堆的單子就是任務佇列。
最後說訊息佇列訊息佇列(MQ)可以理解成兩個應用程式間(生產者消費者間)的通訊,例如簡訊傳送模組,因為模組的傳送速度跟不上,這時候需要有一個容器,暫存一下,緩解下壓力,那麼“訊息佇列”就是在訊息的傳輸過程中儲存訊息的“容器”。然後簡訊模組就可以從容不怕的去訊息佇列取出要發出的簡訊內容,進行傳送處理。