RabbitMQ 詳解(一)------基本概念

一.什麼是MQ?

概念: 消息隊列(MQ):又叫消息中間件。(書面概念不再贅述),通俗講可以理解爲郵局和郵差,用來幫我們存儲和準發消息的。

特點:1.是一個獨立運行的服務,生產者發生消息,消費者接收消費,需要先跟服務器建立連接。

           2.採用隊列作爲數據結構,有先進先出的特點

           3.具有發佈訂閱的模型,消費者可以獲取自己需要的消息。

二.面試常見問題

 問題一:Java有許多隊列的實現,可以解決消息消費的問題,爲什麼還需要消息中間件呢?

     這個問題可以類比有了HashMap,還要用Redis做緩存是一樣的,隊列不能跨進程,不能在分佈式系統中使用,並且沒有持久化機制等等。

 問題二:我們爲什麼要在項目中使用消息中間件?

 1.實現異步通信  

    對數據量大或者處理耗時長的操作,可以使用MQ實現異步通信,減少客戶端的等待,提升響應速度。

ps: 同步通信:發出請求,等待返回。異步通信:發出請求,直接返回,被調用者通過狀態、通知來通知調用者處理

  2.實現系統解耦

     對於改動影響較大的系統之間,引入MQ實現解耦,減少系統之間的直接依賴

      ps 耦合:系統內部或者系統之間存在相互作用,相互影響,相互依賴。

       以一個購物系統爲例,使用傳統的通信方式,訂單系統發生退貨時會依次調用下游系統。如下圖一。但下游系統是並行關係。引入多線程也是可以實現的,但每一個需要並行執行的地方都引入線程,又會帶來線程或者線程池的管理問題。引入消息隊列後如圖二。

    

   3.實現流量削峯

      MQ既然是隊列就具備隊列先進先出的特性,在系統一個特殊瞬間到達峯值時,可以把所有流量承接下來。比如天貓的雙11,如果通過堆硬件的方式去解決,那麼在流量峯值過去之後就會出現巨大的資源浪費。

三.RabbitMQ簡介

  1.rabbitmq的工作模式:

(1)Broker

   RabbitMQ服務器,幫助我們存儲、轉發消息的代理/中介。

(2)Connection

  生產者發送消息/消費者接收消息,都需要跟Broker之間建立一個TCP的長連接

(3)channel

   所有的生產者發送消息和消費者接收消息,都直接創建和釋放TCP長連接的話,對於Broker來說會造成很大的性能損耗。因此引入了Channel(通道)的概念,它是一個虛擬的連接,這樣我們就可以在保持的TCP長連接裏去創建和釋放Channel,大大減少了資源消耗。

(4)Queue

     queue(隊列)真正用來存儲消息的,是一個獨立運行的進程,有自己的數據庫(Mnesia)。
     消費者獲取消息有兩種模式,一種是Push,只要生產者發到服務器,就馬上推送給消費者。另一種是Pull,消息存放在服務端,只有消費者主動獲取才能拿到消息。消費者不需要循環不斷地從隊列獲取消息,可以基於事件機制,實現消費者對隊列的監聽。由於隊列有FIFO的特性,只有確定前一條消息被消費者接收之後,纔會把這條消息從數據庫刪除,繼續投遞下一條消息。

(5)Exchange
         在 RabbitMQ 裏消息不會直接發送到隊列的。而是通過交換機(Exchange)用來實現消息的靈活路由。交換機是一個綁定列表,用來查找匹配的綁定關係。隊列使用綁定鍵(Binding Key)跟交換機建立綁定關係。生產者發送的消息需要攜帶路由鍵,交換機收到消息時會根據它保存的綁定列表,決定將消息路由到哪些與它綁定的隊列上。
 ps:交換機與隊列、隊列與消費者都是多對多的關係。

(6)Vhost
          虛擬主機VHOST。VHOST 可以提高硬件資源的利用率之外,實現資源的隔離和權限的控制。不同的 VHOST中可以有同名的Exchange和Queue,它們是完全透明的。可以使自己的業務系統不跟別人混用一個系統。

2.路由方式

(1)直連 Direct
         隊列與直連類型的交換機綁定,需指定一個精確的綁定鍵。生產者發送消息時會攜帶一個路由鍵。只有當路由鍵與其中的某個綁定鍵完全匹配時,這條消息纔會從交換機路由到滿足路由關係的此隊列上。

                

                channel.basicPublish(“MY_DIRECT_EXCHANGE”,”spring”,”msg1”); 只有第一個隊列能收到消息。

(2)主題 Topic
          隊列與主題類型的交換機綁定時,可以在綁定鍵中使用通配符。兩個通配符:# 0個或者多個單詞,* 不多不少一個單詞單詞,單詞用英文的點“.”隔開的字符。例如abc.def是兩個單詞。

           

           第一個隊列支持路由鍵以junior 開頭的消息路由,後面可以有單詞,也可以沒有。
           第二個隊列支持路由鍵以netty開頭,並且後面是一個單詞的消息路由。
           第三個隊列支持路由鍵以jvm結尾,並且前面是一個單詞的消息路由

          channel.basicPublish("MY_TOPIC_EXCHANGE","junior.fjd.klj","msg 2"); 只有第一個隊列能收到消息。
         channel.basicPublish("MY_TOPIC_EXCHANGE","junior.jvm", "msg 3"); 第一個隊列和第三個隊列能收到消息

(3)廣播 Fanout

            主題類型的交換機與隊列綁定時,不需要指定綁定鍵。因此生產者發送消息到廣播類型的交換機上,也不需要攜帶路由鍵。消息達到交換機時,所有與之綁定了的隊列,都會收到相同的消息的副本。

           

                 channel.basicPublish("MY_FANOUT_EXCHANGE","","msg 4"); 三個隊列都會收到 msg 4。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章