日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RabbitMQ 相关概念

發布時間:2024/4/17 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RabbitMQ 相关概念 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

RabbitMQ 整體上是一個生產者與消費者模型,主要負責接收、存儲和轉發消息。可以把消息傳遞的過程想象成:當你講一個包裹送到郵局,郵局會暫存并最終將郵件通過郵遞員送到收件人的手上,RabbitMQ 就好比由郵局、郵箱和郵遞員組成的一個系統。從計算機術語層面來說,RabbitMQ 模型更像是一種交換機模型。

?

RabbitMQ 的整體模型架構如下圖:

?

生產者和消費者

Producer:生產者,就是投遞消息的一方。

生產者創建消息,然后發不到 RabbitMQ 中。消息一般可以包含 2 個部分:消息體和標簽(Label)。消息體也可以稱之為 payload,在實際應用中,消息體一般是一個帶有業務邏輯結構的數據,比如一個 JSON 字符串。當然可以進一步對這個消息體進行序列化操作。消息的標簽用來表述這條消息,比如一個交換器的名稱和一個路由鍵。生產者把消息交由 RabbitMQ,RabbitMQ 之后會根據標簽把消息發送給感興趣的消費者(Consumer)。

?

Consumer:消費者,就是接收消息的一方。

消費者連接到 RabbitMQ 服務器,并訂閱到隊列上。當消費者消費一條消息時,只是消費消息的消息體(payload)。在消息路由的過程中,消息的標簽會丟棄,存入到隊列中的消息只有消息體,消費者也會消費到消息體,也就不知道消息的生產者是誰,當然消費者也不需要知道。

?

Broker:消息中間件的服務節點。

對于 RabbitMQ 來說,一個 RabbitMQ Broker 可以簡單地看作一個 RabbitMQ 服務節點,或者 RabbitMQ 服務實例。大多數情況下也可以將一個 RabbitMQ Broker 看作一臺 RabbitMQ 服務器。

?

下圖展示了生產者將消息存入 RabbitMQ Broker,以及消費者從 Broker 中消費數據的整個流程。

  首先生產者將業務方數據進行可能的包裝,之后封裝成消息,發送(AMQP 協議里這個動作對應的命令為 Basic.Publish)到 Broker 中。消費者訂閱并接收消息(AMQP 協議里這個動作對應的命令為 Basic.Consume 或者 Basic.Get),經過可能的解包處理得到原始的數據,之后再進行業務處理邏輯。這個業務處理邏輯并不一定需要和接收消息的邏輯使用同一個線程。消費者線程可以使用一個線程去接收消息,存入到內存中,比如使用 Java 中的 BlockingQueue。業務處理邏輯使用另一個線程從內存中讀取數據,這樣可以將應用進一步解耦,提高整個應用的處理效率。

?

?

隊列

Queue:隊列,是 RabbitMQ 的內部對象,用于存儲消息。

  RabbitMQ 中消息只能存儲在隊列中,這一點和 Kafka 這種消息隊列中間件相反。Kafka 將消息存儲在 topic(主題)這個邏輯層面,而相對應的隊列處理邏輯只是 topic 實際存儲文件中的位移標識。RabbitMQ 的生產者生產消息并最終投遞到隊列中,消費者可以從隊列中獲取消息并消費。

  多個消費者可以訂閱同一個隊列,這時隊列中的消息會被平均分攤(Round-Robin,即輪詢)給多個消費者進行處理,而不是每個消費者都接收到所有的消息并處理。

  RabbitMQ 不支持隊列層面的廣播消費,如果需要廣播消費,需要在其上進行二次開發,處理邏輯會變得異常復雜,同時也不建議這么做。

?

?

交換器、路由鍵、綁定

Exchange:交換器。在圖 2-4 中我們暫時可以理解成生產者將消息投遞到隊列中,實際上這個在 RabbitMQ 中不會發生。真實情況是,生產者將消息發送到 Exchange(交換器,通常也可以用大寫的 "X" 來表示),由交換器將消息路由到一個或者多個隊列中。如果路由不到,或許會返回給生產者,或許直接丟棄。這里可以將 RabbitMQ 中的交換器看作一個簡單的實體。

  RabbitMQ 中的交換器有四種類型,不同的類型有著不同的路由策略。

?

RoutingKey:路由鍵。生產者將消息發給交換器的時候,一般會指定一個 RoutingKey,用來指定這個消息的路由規則,而這個 RoutingKey 需要與交換器類型和 綁定鍵(BindingKey)聯合起來才能最終生效。

  在交換器類型和綁定鍵(BindingKey)固定的情況下,生產者可以在發送消息給交換器時,通過指定 RoutingKey 來決定消息流向哪里。

Binding:綁定。RabbitMQ 中通過綁定將 交換器與隊列關聯起來,在綁定的時候一般會指定一個綁定鍵(BindingKey),這樣 RabbitMQ 就指定如何正確地將消息路由到隊列了。

  生產者將消息發送給交換器,需要一個 RoutingKey,當 BindingKey 和 RoutingKey 相匹配時,消息會被路由到對應的隊列中。在綁定多個隊列到同一個交換器的時候,這些綁定允許使用相同的 BindingKey。BindingKey 并不少在所有的情況下都生效,它依賴于交換器類型,比如 fanout 類型的交換器就會無視 BindingKey,而是將消息路由到所有綁定到該交換器的隊列中。

?

  沿用本文開頭的比喻,交換器相當于投遞包裹的郵箱,RoutingKey 相當于寫在包裹上的地址,BindingKey 相當于包裹的目的地,當填寫在包裹上的地址和實際想要投遞的地址相匹配時,那么這個包裹就會被正確投遞到目的地,最后這個目的地的 "主人" -- 隊列可以保留這個包裹。如果填寫的地址出錯,郵遞員不能正確投遞到目的地,包裹可能會回退給寄件人,也有可能被丟棄。

  在某些情形下,RoutingKey 與 BindingKey 可以看作同一個東西。

?

channel.exchangeDeclare(EXCHANGE_NAME, "direct", true, false, null); channel.queueDeclare(QUEUE_NAME, true, false, false, null); channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY); String message = "Hello World!"; channel.basicPublic(EXCHANGE_NAME, ROUTING_KEY,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());

  以上代碼聲明了一個 direct 類型的交換器,然后將交換器和隊列綁定起來。注意這里使用的字樣是 "ROUTING_KEY",在本該使用 BindingKey 的 channel.queueBind 方法中卻和 channel.basicPublish 方法同樣使用了 RoutingKey,這樣做的潛臺詞是:這里的 RoutingKey 和 BindingKey 是同一個東西。在 direct 交換器類型下,RoutingKey 和 BindingKey 需要完全匹配才能使用,所以上面的代碼中采用了這種寫法會顯得方便許多。

  但是在 topic 交換器類型下,RoutingKey 和 BindingKey 之間需要做模糊匹配,兩者并不是相同的。

  BingingKey 其實也屬于路由鍵的一種,官方解釋為:the routing key to use for the binding。可以翻譯為:在綁定的時候使用的路由鍵。大多數時候,包括官方文檔和 RabbitMQ Java API 中都把 BindingKey 和 RoutingKey 看作 RoutingKey,為了避免混淆,可以這么理解:

  在綁定的時候,其中需要的路由鍵是 BindingKey。涉及的客戶端方法如: channel.exchangeBind、channel.queueBind,對應 AMQP 命令為 Exchange.Bind、Queue.Bind。

  發送消息的時候,其中需要的路由鍵是 RoutingKey。涉及的客戶端方法如 channel.basicPublish,對應的 AMQP 命令為 Basic.Publish。

?

  由于某些歷史的原因,包括現存能搜集到的資料顯示:大多數情況下習慣性地將 BindingKey 寫成 RoutingKey,尤其是在使用 direct 類型的交換器的時候。

?

交換器類型

RabbitMQ 常用的交換器類型有 fanout、direct、topic、headers 這四種。AMQP 協議里還提到另外兩種類型:System 和自定義。

?

fanout

它會把所有發送到該交換器的消息路由到所有與該交換器綁定的隊列中。

?

direct

direct 類型的交換器路由規則也很簡單,它會把消息路由到那些 BindingKey 和 RoutingKey 完全匹配的隊列中。

以下圖為例,交換器的類型為 direct,如果我們發送一條消息,并在發送消息的時候設置路由鍵為 "warning",消息會路由到 Queue1 和 Queue2,對應的示例代碼如下:

channel.basicPublish(EXCHANGE_NAME, "warning",MessageProperties.PERSISTENT_TEXT_PLAIN,message.getbytes());

?

  如果 在發送消息的時候設置路由鍵為 "info" 或者 "debug",消息只會路由到 Queue2。如果以其他的路由鍵發送消息,則消息不會路由到這兩個隊列中。

?

topic

前面講到 direct 類型的交換器路由規則是完全匹配 BindingKey 和 RoutingKey,但是這種嚴格的匹配方式在很多情況下不能滿足實際業務的需求。topic 類型的交換器在匹配規則上進行了擴展,它與 direct 類型的交換器相似,也是將消息路由到 BindingKey 和 RoutingKey 相匹配的隊列中,但這里的匹配規則有些不同,它約定:

  RoutingKey 為一個點號 "." 分隔的字符串(被點號 "." 分隔開的每一段獨立的字符串成為一個單詞),如 "com.rabbitmq.client"、"java.util.concurrent"、"com.hidden.client";

  BindingKey 和 RoutingKey 一樣也是點號 ".' 分隔的字符串

  BindingKey 中可以存在兩種特殊字符串 "*" 和 "#",用于做模糊匹配,其中 "*" 用于匹配一個單詞, "#" 用于匹配多個單詞(可以是零個)

  以圖 2-8 中的配置為例:

  路由鍵為 "com.rabbitmq.client" 的消息會同時路由到 Queue1 和 Queue2;

  路由鍵為 "com.hidden.client" 的消息只會路由到 Queue2;

  路由鍵為 "com.hidden.demo" 的消息只會路由到 Queue2;

  路由鍵為 "java.util.concurrent" 的消息將會被丟棄或者返回給生產者(需要設置 mandatory 參數),因為它沒有匹配任何路由鍵。

?

headers

headers 類型的交換器不依賴于路由鍵的匹配規則來路由消息,而是根據發送的消息內容中的 headers 屬性進行匹配。在綁定隊列和交換器時指定一組鍵值對,當發送消息到交換器時,RabbitMQ 會獲取到該消息的 headers(也是一個鍵值對的形式),對比其中的鍵值對是否完全匹配隊列和交換器綁定時指定的鍵值對,如果完全匹配則消息會路由到該隊列,否則不會路由到該隊列。headers 類型的交換器性能會很差,而且也不實用,基本上不會看到它的存在。

?

轉載于:https://www.cnblogs.com/eleven24/p/10327288.html

總結

以上是生活随笔為你收集整理的RabbitMQ 相关概念的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。