1. 程式人生 > >RabbitMQ系列一RabbitMQ基礎概念和使用場景

RabbitMQ系列一RabbitMQ基礎概念和使用場景

RabbitMQ是基於AMQP協議的訊息中介軟體。AMQP中主要有兩個元件:Exchange 和 Queue (在 AMQP 1.0 裡還會有變動),如下圖所示,綠色的 X 就是 Exchange ,紅色的是 Queue ,這兩者都在 Server 端,又稱作 Broker ,這部分是 RabbitMQ 實現的,而藍色的則是客戶端,通常有 Producer 和 Consumer 兩種型別:

RabbitMQ的基礎概念

Broker:簡單來說就是訊息佇列伺服器實體,接受客戶端連線,實現AMQP訊息佇列和路由功能的程序。

vhost:虛擬主機,是一個虛擬概念,類似於許可權控制組,用作不同使用者的許可權分離,一個broker裡可以開設多個vhost,一個vhost裡面可以有若干個Exchange和Queue,但是許可權控制的最小粒度是vhost。

Exchange:訊息交換機,接受生產者傳送的訊息,並根據Binding規則將訊息路由給伺服器中的佇列。ExchangeType決定了Exchange路由訊息的行為,例如在RabbitMQ中,ExchangeType有direct、Fanout和Topic三種,不同型別的Exchange路由的行為是不一樣的。

Queue:訊息佇列載體,用於儲存還未被消費者消費的訊息,每個訊息都會被投入到一個或多個佇列。

Binding:繫結,它的作用就是把exchange和queue按照路由規則繫結起來,Binding聯絡了Exchange與Message Queue。Exchange在與多個Message Queue發生Binding後會生成一張路由表,路由表中儲存著Message Queue所需訊息的限制條件即Binding Key。當Exchange收到Message時會解析其Header得到Routing Key,Exchange根據Routing Key與Exchange Type將Message路由到Message Queue。Binding Key由Consumer在Binding Exchange與Message Queue時指定,而Routing Key由Producer傳送Message時指定,兩者的匹配方式由Exchange Type決定。 

Connection:連線,對於RabbitMQ而言,其實就是一個位於客戶端和Broker之間的TCP連線。

Channel:通道,在客戶端的每個連線裡,可建立多個channel,每個channel代表一個會話任務,僅僅建立了客戶端到Broker之間的連線後,客戶端還是不能傳送訊息的。需要為每一個Connection建立Channel,AMQP協議規定只有通過Channel才能執行AMQP的命令。一個Connection可以包含多個Channel。之所以需要Channel,是因為TCP連線的建立和釋放都是十分昂貴的,如果一個客戶端每一個執行緒都需要與Broker互動,如果每一個執行緒都建立一個TCP連線,暫且不考慮TCP連線是否浪費,就算作業系統也無法承受每秒建立如此多的TCP連線。RabbitMQ建議客戶端執行緒之間不要共用Channel,至少要保證共用Channel的執行緒傳送訊息必須是序列的,但是建議儘量共用Connection。

Routing Key:路由關鍵字,exchange根據這個關鍵字進行訊息投遞。

producer:訊息生產者,就是投遞訊息的程式。

consumer:訊息消費者,就是接受訊息的程式。

Message: 由Header和Body組成,Header是由生產者新增的各種屬性的集合,包括Message是否被持久化、由哪個Message Queue接受、優先順序是多少等。而Body是真正需要傳輸的APP資料。

Command:AMQP的命令,客戶端通過Command完成與AMQP伺服器的互動來實現自身的邏輯。例如在RabbitMQ中,客戶端可以通過publish命令傳送訊息,txSelect開啟一個事務,txCommit提交一個事務。

RabbitMQ的使用場景

非同步處理

場景說明:使用者註冊後,需要給使用者傳送郵件和簡訊,傳統的做法有兩種:

  • 序列的方式
  • 並行的方式

序列方式:將註冊資訊寫入資料庫後,傳送註冊郵件,再發送註冊簡訊,以上三個任務全部完成後才返回給客戶端。 這有一個問題是:傳送郵件和簡訊並不是必須的,它只是一個通知,就算失敗也並不影響註冊,而序列的做法讓客戶端等待沒有必要等待的邏輯。

並行方式:將註冊資訊寫入資料庫後,傳送郵件的同時傳送簡訊,以上三個任務完成後返回給客戶端,並行的方式能提高處理的時間。

假設三個業務節點分別使用50ms,序列方式使用時間150ms,並行使用時間100ms。雖然並行已經提高了處理時間,但是前面說過郵件和簡訊對我正常的使用網站沒有任何影響,客戶端沒有必要等著其傳送完成才顯示註冊成功不應該等待這兩個邏輯的執行。

訊息佇列:註冊成功後,分別把傳送郵件和簡訊的加入到訊息佇列,然後直接返回,讓消費者讀取訊息去處理這兩個邏輯。

引入訊息佇列後,使用者的響應時間就等於寫入資料庫的時間+寫入訊息佇列的時間(可以忽略不計)。

應用解耦

場景:電商系統中使用者下單後訂單系統需要通知庫存系統,傳統的做法是訂單系統呼叫庫存系統的介面。這種做法有一個缺陷:當庫存系統出現故障時,訂單就會失敗(這樣淘寶、京東將少賺好多好多錢),這就是訂單系統和庫存系統高耦合了。引入訊息佇列後,使用者下單,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功。庫存系統訂閱下單的訊息,監聽訊息佇列,獲取下單訊息後進行庫存操作。

優勢:就算庫存系統出現故障,訊息佇列也能保證訊息的可靠投遞,不會導致訊息丟失(馬雲、東哥這下高興了)。

流量削峰

場景:流量削峰一般在秒殺活動中應用廣泛,在秒殺活動中一般會因為流量過大,導致應用掛掉。為了解決這個問題,一般在應用前端加入訊息佇列。

作用:

  • 可以控制活動人數,超過此一定閥值的訂單直接丟棄(直到你為啥一直沒有秒殺成功了吧QAQ)。
  • 可以緩解短時間的高流量壓垮應用(應用程式按自己的最大處理能力獲取訂單)。
  • 使用者的請求,伺服器收到之後,首先寫入訊息佇列,加入訊息佇列長度超過最大值,則直接拋棄使用者請求或跳轉到錯誤頁面。
  • 秒殺業務根據訊息佇列中的請求資訊,再做後續處理。

日誌處理

在大資料日誌處理中可以使用RabbitMQ中介軟體接收日誌系統收集的訊息,使用不同的應用訂閱訊息,比如一個應用可以進行流計算,計算結果通過一些資料視覺化工具來做實時展示,另一個應用對訊息進行歸檔分類,然後儲存到MySQL,我們就可以對這些日誌做一些報表統計。