RabbitMQ 原理介紹及安裝部署

RabbitMQ 原理介紹及安裝部署

標(biāo)簽:RabbitMQ 安裝


簡介

RabbitMQ 是一個用 Erlang 語言開發(fā)的 AMQP 開源實(shí)現(xiàn)。AMQP(Advanced Message Queue Protocol),高級消息隊列協(xié)議,是異步消息處理領(lǐng)域的一個公開標(biāo)準(zhǔn),主要由 Cisco、RedHat 等聯(lián)合制定。而 RabbitMQ 就是 AMQP 的一個開源實(shí)現(xiàn),由 RabbitMQ Technologies Ltd 公司開發(fā)并提供商業(yè)支持。

RabbitMQ 主要應(yīng)用于大型系統(tǒng)中不同的應(yīng)用或者子系統(tǒng)之間的通信,通過分隔數(shù)據(jù)的發(fā)送和接收來解耦應(yīng)用。

一條消息的“一生”

在對 RabbitMQ 進(jìn)行更進(jìn)一步的介紹之前,先讓我們來看一看在 RabbitMQ 中,一條消息,從生產(chǎn)者到消費(fèi)者完整的軌跡。

當(dāng)生產(chǎn)者發(fā)布一條消息時,首先跟 RabbitMQ 建立連接(channel),通過該連接將想要發(fā)布的消息發(fā)送到交換器(exchange)上。交換器通過特定的路由規(guī)則(routing_key),將消息發(fā)送到某個隊列(queue)。RabbitMQ 會監(jiān)控該隊列,一旦發(fā)現(xiàn)有消費(fèi)者訂閱了該隊列,就將消息發(fā)送給消費(fèi)者進(jìn)行處理,然后將該消息從隊列中刪除。

需要注意的是,這里提到的生產(chǎn)者和消費(fèi)者只是消息發(fā)送和接收的概念體現(xiàn),每個客戶端都可以是消費(fèi)者或生產(chǎn)者。

接下來,對上面涉及到的一些重要的概念進(jìn)行進(jìn)一步的介紹。

信道

channel,是消費(fèi)者或生產(chǎn)者與 RabbitMQ 之間的一條連接,本質(zhì)上是 TCP 連接中的一個虛擬連接。在 RabbitMQ 中,消息的發(fā)送和接收、隊列的訂閱等操作都是通過信道完成的。

之所以選擇信道,而不是在 TCP 連接上進(jìn)行命令的發(fā)送,主要是基于性能的考慮。在操作系統(tǒng)中,建立和銷毀 TCP 連接的開銷是很昂貴的。而且,同一時刻,操作系統(tǒng)對于 TCP 連接的數(shù)量也是有限制的,很容易成為性能的瓶頸。而采用信道就不會有這種問題,可以在一個 TCP 連接中,任意的創(chuàng)建多條信道。

路由鍵

routing_key,是一條特定的規(guī)則,決定了消息將要被發(fā)送到哪個隊列。每條消息在發(fā)布的時候,都需要指定自己的 routing_key。

RabbitMQ 通過路由鍵實(shí)現(xiàn)了隊列和交換器之間的綁定。

交換器

exchange,生產(chǎn)者將消息發(fā)送給交換器,然后由交換器根據(jù)路由規(guī)則,決定將消息發(fā)送到哪個隊列。

交換器本質(zhì)上只是一個名稱和一個隊列綁定列表,當(dāng)消息被發(fā)布到交換器時,實(shí)際上是所連接的信道將消息上的路由鍵和交換器中的綁定列表做比較,然后路由消息

在 RabbitMQ 中,常用的交換器類型有三種:direct、fanout 和 topic。下面,對這三種類型的交換器做更進(jìn)一步的介紹。

direct

如果消息中的路由鍵和某個隊列的路由鍵匹配的話,就將消息發(fā)送給該隊列。

RabbitMQ 默認(rèn)實(shí)現(xiàn)了一個名稱為空的 direct 交換器,當(dāng)聲明一個隊列時,如果沒有指定交換器,那么 RabbitMQ 會把該隊列自動綁定到這個默認(rèn)的交換器,并以隊列名稱作為路由鍵。

在 RabbitMQ 中,支持在一個交換器上的多個隊列配置相同的路由鍵。也就是說,對于綁定到交換器 Exchang_A 上的隊列 Queue_1 和 Queue_2,可以設(shè)置同一個 routing_key(假設(shè)為 key_test)。當(dāng)設(shè)置了 routing_key 為 key_test 的消息 Message 被發(fā)布到 Exchang_A 上時,Exchang_A 會將 Message 同時發(fā)送給 Queue_1 和 Queue_2 兩個隊列。

fanout

設(shè)置為 fanout 的交換器,會將消息發(fā)送給所有綁定到它身上的隊列,類似于廣播。

通常應(yīng)用于需要對一條消息做不同反應(yīng)的場景中。比如,在社交網(wǎng)站上,如果用戶上傳了一張照片,在更新用戶相冊的同時,還需要給用戶一些積分獎勵。那么這種情況,就可以使用 fanout 類型的交換器來實(shí)現(xiàn)。只需要將更新用戶相冊的隊列和增加用戶積分的隊列綁定到同一個 fanout 交換器上即可。

topic

topic 類型的交換器,可以使來自不同源頭的消息到達(dá)同一個隊列,即支持在路由鍵中使用通配符。

在 RabbitMQ 中,. 把路由鍵分成多個部分,* 匹配特定位置的任意文本,# 則表示匹配所有規(guī)則。通過對這幾種通配符的組合使用,就可以實(shí)現(xiàn)將不同來源的消息發(fā)送到同一個隊列。比如,將 routing_key 設(shè)置為 *.error ,就可以將所有 routing_key 以 .error 結(jié)尾的消息發(fā)送到同一個隊列。

隊列

queue,生產(chǎn)者發(fā)布的消息最終到達(dá)的地方,同時消費(fèi)者從隊列中消費(fèi)消息。

接收消息

消費(fèi)者主要通過兩種方式從隊列中接收消息:使用 basic.consume 和 basic.get 命令。

當(dāng)消費(fèi)者使用 basic.consume 訂閱了某個隊列后,一旦有消息到達(dá)該隊列,RabbitMQ 就將消息立即發(fā)送給消費(fèi)者,然后等待下一條消息的到來。

如果消費(fèi)者使用的是 basic.get 命令,只會從隊列中獲取單條消息,無法持續(xù)獲取。假如隊列中堆積了 5 條消息,使用 basic.get 命令只會獲得最開始的那條消息,后面的 4 條消息無法獲取。

如果一個隊列有多個消費(fèi)者進(jìn)行訂閱,RabbitMQ 采用輪詢的方式將消息發(fā)送給某個消費(fèi)者,每條消息只發(fā)送給一個消費(fèi)者。

也就是說,如果消費(fèi)者 A、B、C訂閱了同一個隊列,那么第一條消息會發(fā)送給 A,第二條發(fā)送給 B,第三條發(fā)送給 C,第四條發(fā)送給 A,···,以此類推。

當(dāng)消息被消費(fèi)者消費(fèi)了之后,RabbitMQ 就將該消息從隊列中刪除。

那么 RabbitMQ 怎么知道消息被消費(fèi)者成功消費(fèi)了呢?這就涉及到了消息的確認(rèn)機(jī)制。

消息確認(rèn)

消費(fèi)者接收到的每條消息都必須進(jìn)行確認(rèn),如果消費(fèi)者沒有對消息進(jìn)行確認(rèn),那么 RabbitMQ 不會將下一條消息發(fā)送給該消費(fèi)者,直到其對消息進(jìn)行了確認(rèn)。如果在消費(fèi)者向 RabbitMQ 發(fā)送確認(rèn)之前,消費(fèi)者與 RabbitMQ 之間的連接斷開了,那么 RabbitMQ 會將該消息發(fā)送給其他的消費(fèi)者。

主要有兩種確認(rèn)方式:使用 basic.ack 命令向 RabbitMQ 發(fā)送確認(rèn),或者在訂閱隊列時將 auto_ack 參數(shù)設(shè)置為 true。

需要注意的是,如果設(shè)置了 auto_ack 為 true,那么一旦消費(fèi)者接收到了消息,RabbitMQ 就認(rèn)為確認(rèn)了消息,從而將消息從隊列中刪除。但是消費(fèi)者接收到消息并不等同于成功處理了消息,如果在成功處理該條消息之前出現(xiàn)問題或者程序崩潰,由于此時 RabbitMQ 已經(jīng)將消息從隊列中刪除了,那么就意味著這條消息丟失了。

虛擬主機(jī)

vhost,簡化版的 RabbitMQ 服務(wù)器,每一個 vhost 擁有自己的交換器、隊列和綁定。更重要的是,它擁有自己的權(quán)限,不同的 vhost 之間是隔離的??梢詫?vhost 想象成物理服務(wù)器上的虛擬機(jī)。

RabbitMQ 中默認(rèn)的虛擬主機(jī)為:“/”。

消息持久化

默認(rèn)情況下,如果 RabbitMQ 進(jìn)行了重啟,那么隊列、交換器和其中的消息都會丟失。如果想要你的數(shù)據(jù)在重啟后不丟失,那么就需要對消息進(jìn)行持久化設(shè)置。主要操作如下:

  • 將消息的投遞模式(delivery mode)設(shè)置為 2(持久)。

  • 將消息發(fā)送到持久化的交換器。

  • 消息必須到達(dá)持久化的隊列。

RabbitMQ 是通過將消息寫入磁盤中的持久化日志中的方式實(shí)現(xiàn)消息的持久化的。如果持久化隊列中的某條消息被消費(fèi)了,那么 RabbitMQ 會在持久化日志中將該消息標(biāo)記為等待垃圾收集。

管理 RabbitMQ

前面的部分介紹了一些 RabbitMQ 中比較重要的概念和消息的相關(guān)知識,接下來介紹如何對 RabbitMQ 進(jìn)行管理。

首先需要明確一個概念,通常提到的 RabbitMQ 節(jié)點(diǎn),實(shí)際上指的是 RabbitMQ 應(yīng)用和所在的 Erlang 節(jié)點(diǎn)。RabbitMQ 是 Erlang 應(yīng)用程序的一種。

啟動 RabbitMQ 通常使用 rabbitmq-server 工具,但需要注意的是,使用該命令啟動的包括 Erlang 節(jié)點(diǎn)和 RabbitMQ 應(yīng)用。同時,還把 RabbitMQ 應(yīng)用設(shè)置成了獨(dú)立運(yùn)行模式。

對于 RabbitMQ 應(yīng)用的管理,通常使用 rabbitmqctl 工具:

  • stop 參數(shù):將本地節(jié)點(diǎn)干凈的關(guān)閉,包括 RabbitMQ 應(yīng)用和 Erlang 節(jié)點(diǎn)。同時,可以使用 -n rabbit@hostname 參數(shù),關(guān)閉指定的遠(yuǎn)程節(jié)點(diǎn)。

  • stop_app 參數(shù):只關(guān)閉 RabbitMQ 應(yīng)用。

  • start_app 參數(shù):只啟動 RabbitMQ 應(yīng)用。

集群

對于 RabbitMQ 的內(nèi)建集群,主要用于完成兩個設(shè)計目標(biāo):

  • 允許消費(fèi)者和生產(chǎn)者在節(jié)點(diǎn)崩潰的情況下繼續(xù)運(yùn)行。
  • 通過添加更多的節(jié)點(diǎn)來線性擴(kuò)展消息通信吞吐量。

在默認(rèn)情況下,如果集群中某個節(jié)點(diǎn)崩潰了,那么在該節(jié)點(diǎn)上隊列上的消息也就丟失了,因?yàn)?RabbitMQ 不會將節(jié)點(diǎn)上的隊列復(fù)制到整個集群中。

不論是在單節(jié)點(diǎn)系統(tǒng)中還是集群,對于 RabbitMQ 節(jié)點(diǎn)來說,要么是內(nèi)存節(jié)點(diǎn),要么是磁盤節(jié)點(diǎn)。兩者間的主要區(qū)別:

  • 內(nèi)存節(jié)點(diǎn):所有隊列、交換器、綁定、用戶、權(quán)限和 vhost 的元數(shù)據(jù)定義都只是存儲在內(nèi)存中。

  • 磁盤節(jié)點(diǎn):所有的元數(shù)據(jù)信息存儲在磁盤中。對于單節(jié)點(diǎn)系統(tǒng),只允許節(jié)點(diǎn)為磁盤節(jié)點(diǎn)。

當(dāng)在集群中聲明交換器、隊列和綁定時,這些操作會等到集群中所有節(jié)點(diǎn)都成功提交元數(shù)據(jù)后才返回。

在 RabbitMQ 集群中,要求至少有一個磁盤節(jié)點(diǎn),當(dāng)有節(jié)點(diǎn)加入或離開時,需要將該變更通知到至少一個磁盤節(jié)點(diǎn)。

安裝

分別介紹單節(jié)點(diǎn)和集群的安裝部署。

單節(jié)點(diǎn)


依賴

RabbitMQ 是使用 Erlang 編寫的,因此需要安裝 Erlang 庫,以便運(yùn)行 RabbitMQ。

安裝 Erlang

下載 Erlang 源碼

點(diǎn)擊 這里 下載 Erlang 源碼包,并解壓至指定目錄。

配置 ERL_TOP
export ERL_TOP=`pwd`
編譯

使用以下命令進(jìn)行編譯:

./configure --prefix=/path/to/install/erlang
make
make install
設(shè)置環(huán)境變量

編譯完成后,設(shè)置 ERL_HOME。編輯 /etc/profile 文件,增加以下內(nèi)容:

export ERL_HOME=/path/to/install/erlang
export PATH=$PATH:$ERL_HOME/bin
驗(yàn)證

執(zhí)行命令:erl,可以進(jìn)入 Erlang 環(huán)境,證明安裝成功。

下載 RabbitMQ

點(diǎn)擊 這里 下載 RabbitMQ Server 安裝包,并解壓至指定目錄(如:/path/to/install/rabbitmq-server)。

設(shè)置文件夾結(jié)構(gòu)

創(chuàng)建兩個目錄:RabbitMQ 的日志目錄和 Mnesia 數(shù)據(jù)庫目錄。RabbitMQ 使用 Mnesia 數(shù)據(jù)庫存儲服務(wù)器信息,比如隊列元數(shù)據(jù)、虛擬主機(jī)等。

mkdir -p /var/log/rabbitmq
mkdir -p /var/lib/rabbitmq/mnesia/rabbit

啟動

執(zhí)行命令:/path/to/install/rabbitmq-server/sbin/rabbitmq-server 啟動 RabbitMQ Server。
出現(xiàn)以下提示信息,說明啟動成功:

Activating RabbitMQ plugins ...

********************************************************************************
*WARNING* Undefined function global:safe_whereis_name/1
********************************************************************************

0 plugins activated:


+---+   +---+
|   |   |   |
|   |   |   |
|   |   |   |
|   +---+   +-------+
|                   |
| RabbitMQ  +---+   |
|           |   |   |
|   v2.7.0  +---+   |
|                   |
+-------------------+
AMQP 0-9-1 / 0-9 / 0-8
Copyright (C) 2007-2011 VMware, Inc.
Licensed under the MPL.  See http://www.rabbitmq.com/

node           : rabbit@172-23-8-23
app descriptor : /home/xuzhidan/bigdata/RabbitMQ/rabbitmq_server-2.7.0/sbin/../ebin/rabbit.app
home dir       : /root
config file(s) : (none)
cookie hash    : TJy1BzDGsu3ovCCTHWG7rw==
log            : /var/log/rabbitmq/rabbit@172-23-8-23.log
sasl log       : /var/log/rabbitmq/rabbit@172-23-8-23-sasl.log
database dir   : /var/lib/rabbitmq/mnesia/rabbit@172-23-8-23
erlang version : 8.3

-- rabbit boot start
starting file handle cache server                                     ...done
starting worker pool                                                  ...done
starting database                                                     ...done
starting codec correctness check                                      ...done
-- external infrastructure ready
starting plugin registry                                              ...done
starting auth mechanism cr-demo                                       ...done
starting statistics event manager                                     ...done
starting logging server                                               ...done
starting auth mechanism amqplain                                      ...done
starting auth mechanism plain                                         ...done
starting exchange type direct                                         ...done
starting exchange type fanout                                         ...done
starting exchange type headers                                        ...done
starting exchange type topic                                          ...done
-- kernel ready
starting node monitor                                                 ...done
starting cluster delegate                                             ...done
starting guid generator                                               ...done
starting alarm handler                                                ...done
starting memory monitor                                               ...done
-- core initialized
starting empty DB check                                               ...done
starting exchange, queue and binding recovery                         ...done
starting mirror queue slave sup                                       ...done
starting adding mirrors to queues                                     ...done
-- message delivery logic ready
starting error log relay                                              ...done
starting networking                                                   ...done
starting direct_client                                                ...done
starting notify cluster nodes                                         ...done

broker running

集群


需要在集群中的所有節(jié)點(diǎn)上安裝 RabbitMQ,具體安裝步驟參照上面單節(jié)點(diǎn)的安裝過程。

同步 cookie 文件

RabbitMQ 集群是通過 Erlang 的集群實(shí)現(xiàn)的,當(dāng)集群中的節(jié)點(diǎn)進(jìn)行通信時,Erlang 節(jié)點(diǎn)會進(jìn)行認(rèn)證。如果節(jié)點(diǎn)之間的 Erlang cookie 不相同,則會認(rèn)證失敗。因此,需要在集群中的所有節(jié)點(diǎn)上同步 cookie 文件。

拷貝 cookie

如果是通過上面介紹的單節(jié)點(diǎn)的方式安裝的 RabbitMQ,則 Erlang 的 cookie 文件路徑為:/root/.erlang.cookie。

將集群中任意一個節(jié)點(diǎn)上的 cookie 文件拷貝到其他的節(jié)點(diǎn)上,進(jìn)行替換。

修改權(quán)限

RabbitMQ 在啟動每個節(jié)點(diǎn)時,會檢查節(jié)點(diǎn)上的 cookie 文件的權(quán)限,必須為 400,否則會報錯。因此需要將每個節(jié)點(diǎn)上的 cookie 文件的權(quán)限修改為 400 。

配置主機(jī)名

設(shè)置主機(jī)名

RabbitMQ 是通過主機(jī)名來對節(jié)點(diǎn)進(jìn)行管理的,因此需要對集群中的每個節(jié)點(diǎn)都設(shè)置一個唯一的主機(jī)名。

可通過修改配置文件 /etc/sysconfig/network 永久修改主機(jī)名。

添加 IP 主機(jī)名映射

修改節(jié)點(diǎn)上的 /etc/hosts 文件,添加集群中所有節(jié)點(diǎn)的IP和主機(jī)名映射,并在集群中同步。

啟動集群

假設(shè)集群中有三個節(jié)點(diǎn):host1、host2和host3,通過以下步驟將整個集群啟動。

啟動服務(wù)

在 host1 上執(zhí)行以下命令,啟動服務(wù):

cd /path/to/install/rabbitmq-server 
sh sbin/rabbitmq-server -detached

在 host2 和 host3 上執(zhí)行以下命令,啟動服務(wù),并重置 RabbitMQ 應(yīng)用:

cd /path/to/install/rabbitmq-server 
sh sbin/rabbitmq-server -detached
sh sbin/rabbitmqctl stop_app
sh sbin/rabbitmqctl reset
加入集群

在 host2 和 host3 上分別執(zhí)行以下命令,加入到集群中

cd /path/to/install/rabbitmq-server 
sh sbin/rabbitmqctl cluster rabbit@host1 rabbit@host2

其中,host1 和 host2 作為集群中的磁盤節(jié)點(diǎn),host3 作為集群中的內(nèi)存節(jié)點(diǎn)。

啟動 RabbitMQ 應(yīng)用

在 host2 和 host 3 上分別執(zhí)行以下命令,啟動 RabbitMQ 應(yīng)用程序:

cd /path/to/install/rabbitmq-server 
sh sbin/rabbitmqctl start_app
查看狀態(tài)

執(zhí)行以下命令,查看集群的狀態(tài):

cd /path/to/install/rabbitmq-server 
sh sbin/rabbitmqctl cluster_status

顯示以下信息,說明集群部署成功:

[root@172-23-8-24 rabbitmq_server-2.7.0]# sbin/rabbitmqctl cluster_status
Cluster status of node 'rabbit@172-23-8-24' ...
[{nodes,[{disc,['rabbit@172-23-8-24','rabbit@172-23-8-23']}]},
 {running_nodes,['rabbit@172-23-8-23','rabbit@172-23-8-24']}]
...done.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于消息隊列,從前年開始斷斷續(xù)續(xù)看了些資料,想寫很久了,但一直沒騰出空,近來分別碰到幾個朋友聊這塊的技術(shù)選型,是時...
    預(yù)流閱讀 586,573評論 51 787
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • 利用RabbitMQ集群橫向擴(kuò)展能力,均衡流量壓力,讓消息集群的秒級服務(wù)能力達(dá)到百萬,Google曾做過此類實(shí)驗(yàn);...
    有貨技術(shù)閱讀 3,620評論 0 1
  • 來源 RabbitMQ是用Erlang實(shí)現(xiàn)的一個高并發(fā)高可靠AMQP消息隊列服務(wù)器。支持消息的持久化、事務(wù)、擁塞控...
    jiangmo閱讀 10,505評論 2 34
  • RabbitMQ采用Erlang編寫,需安裝語言庫才能運(yùn)行RabbitMQ代理服務(wù)器。AMQP:高級消息隊列協(xié)議。...
    JAVA覓音閣閱讀 4,007評論 0 7

友情鏈接更多精彩內(nèi)容