一、MQ 全稱為 Message Queue, 消息隊列( MQ )
是一種應用程序對應用程序的通信方法。應用程序通過讀寫出入隊列的消息(針對應用程序的數據)來通信,而無需專用連接來鏈接它們。
消息傳遞指的是程序之間通過在消息中發送數據進行通信,而不是通過直接調用彼此來通信,直接調用通常是用於諸如遠程過程調用的技術。排隊指的是應用程序通過隊列來通信。隊列的使用除去了接收和發送應用程序同時執行的要求。
排隊指的是應用程序通過 隊列來通信。隊列的使用除去了接收和發送應用程序同時執行的要求。
二、AMQP 即 Advanced Message Queuing Protocol
高級消息隊列協議,是應用層協議的一個開放標准,為面向消息的中間件設計。消息中間件主要用於組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。
AMQP 的主要特征是面向消息、隊列、路由(包括點對點和發布 / 訂閱)、可靠性、安全。
三、 Rabbitmq概念:
屬於一個流行的開源消息隊列系統。屬於AMQP( 高級消息隊列協議 ) 標准的一個 實現。是應用層協議的一個開放標准,為面向消息的中間件設計。用於在分布式系統中存儲轉發消息,在 易用性、擴展性、高可用性等方面表現不俗。
消息中間件主要用於組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。
AMQP 的主要特征是面向消息、隊列、路由(包括點對點和發布 / 訂閱)、可靠性、安全。
RabbitMQ特點:
使用Erlang編寫
支持持久化
支持HA
提供C# , erlang,java,perl,python,ruby等的client開發端
四、什么是耦合、解耦合
一、耦合
1、耦合是指兩個或兩個以上的體系或兩種運動形式間通過相互作用而彼此影響以至聯合起來的現象。
2、在軟件工程中,對象之間的耦合度就是對象之間的依賴性。對象之間的耦合越高,維護成本越高,因此對象的設計應使類和構件之間的耦合最小。
3、分類:有軟硬件之間的耦合,還有軟件各模塊之間的耦合。耦合性是程序結構中各個模塊之間相互關聯的度量。它取決於各個模塊之間的接口的復雜程度、調用模塊的方式以及哪些信息通過接口。
二、解耦
1、解耦,字面意思就是解除耦合關系。
2、在軟件工程中,降低耦合度即可以理解為解耦,模塊間有依賴關系必然存在耦合,理論上的絕對零耦合是做不到的,但可以通過一些現有的方法將耦合度降至最低。
3、設計的核心思想:盡可能減少代碼耦合,如果發現代碼耦合,就要采取解耦技術。讓數據模型,業務邏輯和視圖顯示三層之間彼此降低耦合,把關聯依賴降到最低,而不至於牽一發而動全身。原則就是A功能的代碼不要寫在B的功能代碼中,如果兩者之間需要交互,可以通過接口,通過消息,甚至可以引入框架,但總之就是不要直接交叉寫。
五、RabbitMQ中的概念名詞
Broker:簡單來說就是消息隊列服務器實體。
Exchange:消息交換機,它指定消息按什么規則,路由到哪個隊列。
Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來。
Routing Key:路由關鍵字, exchange根據這個關鍵字進行消息投遞。
vhost:虛擬主機,一個broker里可以開設多個vhost,用作不同用戶的權限分離。
producer:消息生產者,就是投遞消息的程序。
consumer:消息消費者,就是接受消息的程序。
channel:消息通道,在客戶端的每個連接里,可建立多個channel,每個channel代表一個會話任務。
六、RabbitMQ工作理
MQ 是消費 - 生產者模型的一個典型的代表,一端往消息隊列中不斷寫入消息,而另一端則可以讀取或者訂閱隊列中的消息。 MQ 則是遵循了 AMQP協議的具體實現和產品。在項目中,將一些無需即時返回且耗時的操作提取出來,進行了異步處理,而這種異步處理的方式大大的節省了服務器的請求響應時間,從而提高了系統的吞吐量。
( 1)客戶端連接到消息隊列服務器,打開一個channel。
( 2)客戶端聲明一個exchange,並設置相關屬性。
( 3)客戶端聲明一個queue,並設置相關屬性。
( 4)客戶端使用routing key,在exchange和queue之間建立好綁定關系。
( 5)客戶端投遞消息到exchange。
( 6) exchange接收到消息后,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列里
七、Rabbitmq 的 metadata
元數據可以持久化在 RAM 或 Disc. 從這個角度可以把 RabbitMQ 集群中的節點分成兩種 :RAM Node和 Disk Node.
RAM Node 只會將元數據存放在RAM
Disk node 會將元數據持久化到磁盤。
單節點系統就沒有什么選擇了 , 只允許 disk node, 否則由於沒有數據冗余一旦重啟就會丟掉所有的配置信息 . 但在集群環境中可以選擇哪些節點是 RAM node.在集群中聲明(declare) 創建 exchange queue binding, 這類操作要等到所有的節點都完成創建才會返回 :
如果是內存節點就要修改內存數據 ,
如果是 disk node 就要等待寫磁盤 , 節點過多這里的速度就會被大大的拖慢 .
有些場景 exchang queue 相當固定 , 變動很少 ,那即使全都是 disc node, 也沒有什么影響 . 如果使用 Rabbitmq 做 RPC( RPC :Remote Procedure Call—遠程過程調用), RPC 或者類似 RPC 的場景這個問題就嚴重了 , 頻繁創建銷毀臨時隊列 , 磁盤讀寫能力就很快成為性能瓶頸了。所以 , 大多數情況下 , 我們盡量把 Node 創建為RAM Node. 這里就有一個問題了 , 要想集群重啟后元數據可以恢復就需要把集群元數據持久化到磁盤 , 那需要規划 RabbitMQ 集群中的 RAM Node 和 Disc Node 。
只要有一個節點是 Disc Node 就能提供條件把集群元數據寫到磁盤 ,RabbitMQ 的確也是這樣要求的 : 集群中只要有一個 disk node 就可以 , 其它的都可以是 RAM node. 節點加入或退出集群一定至少要通知集群中的一個 disk node 。
如果集群中 disk node 都宕掉 , 就不要變動集群的元數據 . 聲明 exchange queue 修改用戶權限 , 添加用戶等等這些變動在節點重啟之后無法恢復 。
有一種情況要求所有的 disk node 都要在線情況在才能操作 , 那就是增加或者移除節點 .RAM node 啟動的時候會連接到預設的 disk node 下載最新的集群元數據 . 如果你有兩個 disk node(d1 d2), 一個 RAM node 加入的時候你只告訴 d1, 而恰好這個 RAM node 重啟的時候 d1 並沒有啟動 , 重啟就會失敗 . 所以加入 RAM 節點的時候 , 把所有的disk node 信息都告訴它 ,RAM node 會把 disk node 的信息持久化到磁盤以便后續啟動可以按圖索驥 .
八、Rabbitmq 集群部署