MQ全稱爲Message Queue, 消息隊列(MQ)是一種應用程序對應用程序的通訊方法。應用程序經過讀寫出入隊列的消息(針對應用程序的數據)來通訊,而無需專用鏈接來連接它們。node
消息傳遞指的是程序之間經過在消息中發送數據進行通訊,而不是經過直接調用彼此來通訊,直接調用一般是用於諸如遠程過程調用的技術。python
排隊指的是應用程序經過 隊列來通訊。隊列的使用除去了接收和發送應用程序同時執行的要求。linux
RabbitMQ是由Erlang語言編寫的實現了高級消息隊列協議(AMQP)的開源消息代理軟件(也可稱爲 面向消息的中間件)。支持Windows、Linux/Unix、MAC OS X操做系統和包括JAVA在內的多種編程語言.web
AMQP,即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不一樣產品,不一樣的開發語言等條件的限制。正則表達式
RabbitMQ使用場景: # 1)異步處理; # 2)應用解耦; # 3)流量削峯; # 4)消息通信;
全部MQ產品從模型抽象上來講都是同樣的過程: 消費者(consumer)訂閱某個隊列。生產者(producer)建立消息,而後發佈到隊列(queue)中
編程
上面只是最簡單的描述,具體到RabbitMQ則有更詳細的概念解釋,上面介紹過RabbitMQ是AMQP協議的一個開源實現,因此其內部實際上也是AMQP中的基本概念:vim
Message消息, 消息是不具名的,他由消息頭和消息體組成。消息體是不透明的,而消息頭則由一系列的可選屬性組成,這些屬性包括routing-key(路由鍵)、priority(相對於其餘消息的優先權)、delivery-mode(指出該消息可能須要持久性存儲)等。瀏覽器
路由鍵:
routing_key,是一條特定的規則,決定了消息將要發送到那個隊列,每條消息在發佈的時間都須要指定本身的routing_key
緩存
RabbitMQ 經過路由鍵實現了隊列和交換器之間的綁定.
安全
Publisher:消息的生產者,也是一個向交換器發佈消息的客戶端應用程序。
Exchange: 交換器,用來接收生產者發送的消息並將這些消息路由給服務器中的隊列。
Binding: 綁定, 用於消息隊列和交換器之間的關聯,一個綁定就是基於路由鍵將交換器和消息隊列鏈接起來的路由規則, 因此能夠將交換器理解成一個由綁定構成的路由表。
Queue: 消息隊列,用來保存消息直到發送給消費者,他是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列裏面,等待消費者鏈接到這個隊列將其取走。
Connection: 網絡鏈接,好比一個TCP鏈接。
Channel信道: 多路複用鏈接中的一條獨立的雙向數據流通道。通道是創建在真實的TCP鏈接內地虛擬鏈接,AMQP命令都是經過信道發出去的,無論是發佈消息、訂閱隊列仍是接受消息,這些動做都是經過信道完成,由於對於操做系統來講創建和銷燬TCP都是很是昂貴的開銷,因此引入了信道的概念,以複用一條TCP鏈接。
Consumer: 消息的消費者,表示一個從消息隊列中取得消息的客戶端應用程序。
Virtual Host: 虛擬主機, 表示一批交換器、消息隊列和相關對象。虛擬主機是共享相同身份認證和加密環境的獨立服務器械。每一個vhost本質上就是一個mini版的RabbitMQ服務器,擁有本身的隊列、交換器、綁定和權限機制。vhost是AMQP概念的基礎,必須在鏈接時指定,RabbitMQ默認的vhost是/。
Broker: 表示消息隊列服務器實體。
若是看完上面概述,看這裏還有點吃力,能夠看一下下面詳細描述
當生產者發佈一條消息時,首先跟RabbitMQ創建鏈接(channel),經過該鏈接將想要發佈的消息發送到交換器(exchange)上。交換器經過特定的路由規則(routing_key),將消息發送到某個隊列(queue)。RabbitMQ會監控該隊列,一旦發現有消費者訂閱了該隊列,就將消息發送給消費者進行處理,而後將該消息從隊列中刪除。
須要注意的是,這裏提到的生產者和消費者只是消息發送和接受的概念體現,每一個客戶端均可以是消費者或生產者。
若是項目須要發佈消息,那麼必需要連接到 RabbitMQ,而項目於 RabbitMQ之間使用 TCP 鏈接,加入每次發佈消息都要鏈接TCP,這不只會形成鏈接資源嚴重浪費,會形成服務器性能瓶頸,因此 RabbitMQ 爲全部的線程只用一條 TCP 鏈接,怎麼實現的呢?
RabbitMQ 引入了信道的概念,全部須要發佈消息的線程都包裝成一條信道在 TCP 中傳輸,理論上 一條 TCP 鏈接支持無限多個信道,模型以下:
消息隊列,用來保存消息直到發送給消費者。它是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列裏面,等待消費者鏈接到這個隊列將其取走。
消費者主要經過兩種方式從隊列中接受消息: 使用basic.consume和basic.get命令
當消費者使用basic.consume訂閱了某個隊列後,一旦有消息到達該隊列,RabbitMQ就將消息當即發送給消費者,而後等待下一條消息的到來。
若是消費者使用的是basic.get命令,只會從隊列中獲取單條消息,沒法持續獲取。假如隊列中堆積了5條消息,使用basic.get命令只會得到最開始的那條消息,後面的4條消息沒法獲取。
若是一個隊列有多個消費者進行訂閱,RabbitMQ採用輪訓的方式將消息發送給某個消費者,每條消息只發送給一個消費者。
也就是說,若是消費者A、B、C訂閱了同一個隊列,那麼第一條消息會發送給A,第二條會發送給B,第三條發送給C,第四條發送給A,..,以此類推。
當消息被消費者消費了以後,RabbitMQ就將改消息從隊列中刪除。
那麼 RabbitMQ 怎麼知道消息被消費者成功消費了呢?這就涉及到了消息的確認機制。
消費者接收到的每條消息都必須進行確認,若是消費者沒有對消息進行確認,那麼 RabbitMQ 不會將下一條消息發送給該消費者,直到其對消息進行了確認。若是在消費者向 RabbitMQ 發送確認以前,消費者與 RabbitMQ 之間的鏈接斷開了,那麼 RabbitMQ 會將該消息發送給其餘的消費者。
.
主要有兩種確認方式: 使用basic.ack命令向RabbitMQ發送確認,或者在訂閱隊列時將auto_ack參數設置爲true
.
須要注意的是,若是設置了 auto_ack 爲 true,那麼一旦消費者接收到了消息,RabbitMQ 就認爲確認了消息,從而將消息從隊列中刪除。可是消費者接收到消息並不等同於成功處理了消息,若是在成功處理該條消息以前出現問題或者程序崩潰,因爲此時 RabbitMQ 已經將消息從隊列中刪除了,那麼就意味着這條消息丟失了。
默認狀況下,若是RabbitMQ進行了重啓,那麼隊列,交換器和其中的消息都會丟失,若是想要你的數據在重啓後不丟失,那麼就須要對消息進行持久化設置,主要操做以下:
RabbitMQ 是經過將消息寫入磁盤中的持久化日誌中的方式實現消息的持久化的。若是持久化隊列中的某條消息被消費了,那麼 RabbitMQ 會在持久化日誌中將該消息標記爲等待垃圾收集。
綁定,用於消息隊列和交換器之間的關聯。一個綁定就是基於路由鍵將交換器和消息隊列鏈接起來的路由規則,因此能夠將交換器理解成一個由綁定構成的路由表,以下:
咱們向 RabbitMQ 發送消息,其實是把消息發到交換器了,再由交換器根據相關路由規則發到特定隊列上,在隊列上監聽的消費者就能夠進行消費了,目前 RabbitMQ 共四種類型:
direct、fanout、topic、headers 。headers 匹配 AMQP 消息的 header 而不是路由鍵,
此外 headers 交換器和 direct 交換器徹底一致,但性能差不少,目前幾乎用不到了,因此直接看另外三種類型:
direct交換器
消息中的路由鍵(routing key)若是和 Binding 中的 binding key 一致, 交換器就將消息發到對應的隊列中。路由鍵與隊列名徹底匹配,若是一個隊列綁定到交換機要求路由鍵爲「dog」,則只轉發 routing key 標記爲「dog」的消息,不會轉發「dog.puppy」,也不會轉發「dog.guard」等等。它是徹底匹配、單播的模式。
fanout交換器
每一個發送到 fanout 交換器中的消息,他不會去匹配路由鍵,直接把消息投遞到全部綁定到 fanout 交換器中的隊列上,它就像一個廣播站同樣,它會向全部收聽廣播的用戶發送消息。對應到系統上,它容許你針對一個消息做不一樣操做,好比用戶上傳了一張新的圖片,系統要同時對這個事件進行不一樣的操做,好比刪除舊的圖片緩存、增長積分獎勵等等。這樣就大大下降了系統之間的耦合度了。
topic交換器
topic 交換器有點相似於 direct 交換器,它經過模式匹配分配消息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時隊列須要綁定到一個模式上。它將路由鍵和綁定鍵的字符串切分紅單詞,這些單詞之間用點隔開。它一樣也會識別兩個通配符:符號「#」和符號「」。#匹配0個或多個單詞,匹配很少很多一個單詞。
前面的部分介紹了一些 RabbitMQ 中比較重要的概念和消息的相關知識,接下來介紹如何對 RabbitMQ 進行管理。
首先須要明確一個概念,一般提到的 RabbitMQ 節點,實際上指的是 RabbitMQ 應用和所在的 Erlang 節點。RabbitMQ 是 Erlang 應用程序的一種。
啓動 RabbitMQ 一般使用
rabbitmq-server
工具,但須要注意的是,使用該命令啓動的包括 Erlang 節點和 RabbitMQ 應用。同時,還把 RabbitMQ 應用設置成了獨立運行模式。對於 RabbitMQ 應用的管理,一般使用
rabbitmqctl
工具:
stop 參數: # 將本地節點乾淨的關閉,包括 RabbitMQ 應用和 Erlang 節點。 # 同時,可使用 `-n rabbit@hostname` 參數,關閉指定的遠程節點。 stop_app 參數: # 只關閉 RabbitMQ 應用。 start_app 參數: # 只啓動 RabbitMQ 應用。
# 在項目中想要 RabbitMQ 變得更加健壯,就要使得其變成高可用,因此咱們要搭建一個 RabbitMQ 集羣,這樣你能夠從任何一臺 RabbitMQ 故障中得以倖免,而且應用程序可以持續運行而不會發生阻塞。而 RabbitMQ 自己是基於 Erlang 編寫的,Erlang 天生支持分佈式(經過同步 Erlang 集羣各節點的 cookie 來實現),所以不須要像 ActiveMQ、Kafka 那樣經過 ZooKeeper 分別來實現 HA 方案和保存集羣的元數據.
RabbitMQ 內部有各類基礎構件,包括隊列、交換器、綁定、虛擬主機等,他們組成了 AMQP 協議消息通訊的基礎,而這些構件以元數據的形式存在,它始終記錄在 RabbitMQ 內部,它們分別是:
# 隊列元數據:隊列名稱和它們的屬性 # 交換器元數據:交換器名稱、類型和屬性 # 綁定元數據:一張簡單的表格展現瞭如何將消息路由到隊列 # vhost元數據:爲 vhost 內的隊列、交換器和綁定提供命名空間和安全屬性
這裏有個問題須要思考,RabbitMQ 默認會將消息冗餘到全部節點上嗎?這樣聽起來正符合高可用的特性,只要集羣上還有一個節點存活,那麼就能夠繼續進行消息通訊,但這也隨之爲 RabbitMQ 帶來了致命的缺點:
- 每次發佈消息,都要把它擴散到全部節點上,並且對於磁盤節點來講,每一條消息都會觸發磁盤活動,這會致使整個集羣內性能負載急劇拉昇。
- 若是每一個節點都有全部隊列的完整內容,那麼添加節點不會給你帶來額外的存儲空間,也會帶來木桶效應,舉個例子,若是集羣內有個節點存儲了 3G 隊列內容,那麼在另一個只有 1G 存儲空間的節點上,就會形成內存空間不足的狀況,也就是沒法經過集羣節點的擴容提升消息積壓能力。
解決這個問題就是經過集羣中惟一節點來負責任何特定隊列,只有該節點纔會受隊列大小的影響,其它節點若是接收到該隊列消息,那麼就要根據元數據信息,傳遞給隊列全部者節點(也就是說其它節點上只存儲了特定隊列全部者節點的指針)。這樣一來,就能夠經過在集羣內增長節點,存儲更多的隊列數據.
交換器實際上是咱們想象出來的,它本質是一張查詢表,裏面包括了交換器名稱和一個隊列的綁定列表,當你將消息發佈到交換器中,其實是你所在的信道將消息上的路由鍵與交換器的綁定列表進行匹配,而後將消息路由出去。有了這個機制,那麼在全部節點上傳遞交換器消息將簡單不少,而 RabbitMQ 所作的事情就是把交換器拷貝到全部節點上,所以每一個節點上的每條信道均可以訪問完整的交換器了。
關於上面隊列所說的問題與解決辦法,又有了一個伴隨而來的問題出現:若是特定隊列的全部者節點發生了故障,那麼該節點上的隊列和關聯的綁定都會消失嗎?
- 若是是內存節點,那麼附加在該節點上的隊列和其關聯的綁定都會丟失,而且消費者能夠從新鏈接集羣並從新建立隊列;
- 若是是磁盤節點,從新恢復故障後,該隊列又能夠進行傳輸數據了,而且在恢復故障磁盤節點以前,不能在其它節點上讓消費者從新連到集羣並從新建立隊列,若是消費者繼續在其它節點上聲明該隊列,會獲得一個 404 NOT_FOUND 錯誤,這樣確保了當故障節點恢復後加入集羣,該節點上的隊列消息不回丟失,也避免了隊列會在一個節點以上出現冗餘的問題。
接下來講說內存節點與磁盤節點在集羣中的做用,在集羣中的每一個節點,要麼是內存節點,要麼是磁盤節點,若是是內存節點,會將全部的元數據信息僅存儲到內存中,而磁盤節點則不只會將全部元數據存儲到內存上, 還會將其持久化到磁盤。
在單節點 RabbitMQ 上,僅容許該節點是磁盤節點,這樣確保了節點發生故障或重啓節點以後,全部關於系統的配置與元數據信息都會重磁盤上恢復;而在 RabbitMQ 集羣上,容許節點上至少有一個磁盤節點,在內存節點上,意味着隊列和交換器聲明之類的操做會更加快速。緣由是這些操做會將其元數據同步到全部節點上,對於內存節點,將須要同步的元數據寫進內存就好了,但對於磁盤節點,意味着還須要及其消耗性能的磁盤寫入操做。
RabbitMQ 集羣只要求至少有一個磁盤節點,這是有道理的,當其它內存節點發生故障或離開集羣,只須要通知至少一個磁盤節點進行元數據的更新,若是是碰巧惟一的磁盤節點也發生故障了,集羣能夠繼續路由消息,可是不能夠作如下操做了:
# 建立隊列 # 建立交換器 # 建立綁定 # 添加用戶 # 更改權限 # 添加或刪除集羣節點
這是由於上述操做都須要持久化到磁盤節點上,以便內存節點恢復故障能夠從磁盤節點上恢復元數據,解決辦法是在集羣添加 2 臺以上的磁盤節點,這樣其中一臺發生故障了,集羣仍然能夠保持運行,且可以在任什麼時候候保存元數據變動。
CentOS7.3.1611 Package: rabbitmq-server-3.3.5-34
節點名 | IP | 軟件版本 | 硬件 | 網絡 | 說明 |
---|---|---|---|---|---|
rabbitmq-1 | 192.168.171.135 | list 裏面 | 2C4G | Nat,內網 | 測試環境 |
rabbitmq-2 | 192.168.171.134 | list裏面 | 2C4G | Nat,內網 | 測試環境 |
init_security() { systemctl stop firewalld systemctl disable firewalld &>/dev/null setenforce 0 sed -i '/^SELINUX=/ s/enforcing/disabled/' /etc/selinux/config sed -i '/^GSSAPIAu/ s/yes/no/' /etc/ssh/sshd_config sed -i '/^#UseDNS/ {s/^#//;s/yes/no/}' /etc/ssh/sshd_config systemctl enable sshd crond &> /dev/null rpm -e postfix --nodeps echo -e "\033[32m [安全配置] ==> OK \033[0m" } init_security init_yumsource() { if [ ! -d /etc/yum.repos.d/backup ];then mkdir /etc/yum.repos.d/backup fi mv /etc/yum.repos.d/* /etc/yum.repos.d/backup 2>/dev/null if ! ping -c2 www.baidu.com &>/dev/null then echo "您沒法上外網,不能配置yum源" exit fi curl -o /etc/yum.repos.d/163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo &>/dev/null curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo &>/dev/null yum clean all timedatectl set-timezone Asia/Shanghai echo "nameserver 114.114.114.114" > /etc/resolv.conf echo "nameserver 8.8.8.8" >> /etc/resolv.conf chattr +i /etc/resolv.conf yum -y install ntpdate ntpdate -b ntp1.aliyun.com echo -e "\033[32m [YUM Source] ==> OK \033[0m" } init main() { init_security init_yumsource }
因爲 RabbitMQ 集羣鏈接是經過主機名來鏈接服務的,必須保證各個主機名之間能夠 ping 通
hostnamectl set-hostname rabbitmq-2 hostnamectl set-hostname rabbitmq-1 echo "192.168.171.134 rabbitmq-2" >> /etc/hosts echo "192.168.171.135 rabbitmq-1" >> /etc/hosts scp /etc/hosts rabbitmq-1:/etc/
# 更新 yum源 yum install epel-release yum -y install rabbitmq-server
RabbitMQ 集羣是經過 Erlang 的集羣實現的,當集羣中的節點進行通訊時,Erlang 節點會進行認證。若是節點之間的 Erlang cookie 不相同,則會認證失敗。所以,須要在集羣中的全部節點上同步 cookie 文件
這裏將 rabbitmq-1 的該文件複製到 rabbitmq-2,因爲這個文件權限是 400 爲方便傳輸,先修改權限,非必須操做,因此須要先修改 rabbitmq-2 中的該文件權限爲 777
[root@rabbitmq-1 ~]# service rabbitmq-server start Redirecting to /bin/systemctl start rabbitmq-server.service [root@rabbitmq-1 ~]# cat /var/lib/rabbitmq/.erlang.cookie KNTAXWSNMNNODXVTCRZZ # 用scp 拷貝到rabbitmq-2 scp /var/lib/rabbitmq/.erlang.cookie rabbitmq-2:/var/lib/rabbitmq/.erlang.cookie # 咱們到另外一臺機器發現拷貝過來的權限有問題,因此須要修改 [root@rabbitmq-2 ~]# ls -l /var/lib/rabbitmq/.erlang.cookie -r-------- 1 root root 20 May 7 23:27 /var/lib/rabbitmq/.erlang.cookie chmod 400 /var/lib/rabbitmq/.erlang.cookie chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie service rabbitmq-server start
在rabbitmq-2執行以下命令
[root@rabbitmq-2 ~]# rabbitmqctl stop_app # 中止rabbitmq服務 [root@rabbitmq-2 ~]# rabbitmqctl reset # 清空節點狀態 [root@rabbitmq-2 ~]# rabbitmqctl join_cluster rabbit@node1 # node2和node1構成集羣,node2必須能經過node1的主機名ping通 [root@rabbitmq-2 ~]# rabbitmqctl start_app # 開啓rabbitmq服務 # 接下來咱們到任意一臺機器上面查看集羣狀態: [root@rabbitmq-2 ~]# rabbitmqctl cluster_status Cluster status of node 'rabbit@rabbitmq-1' ... [{nodes,[{disc,['rabbit@rabbitmq-1','rabbit@rabbitmq-2']}]}, {running_nodes,['rabbit@rabbitmq-2','rabbit@rabbitmq-1']}, {cluster_name,<<"rabbit@rabbitmq-1">>}, {partitions,[]}] ...done.
rabbitmqctl list_users # 查看rabbitmq用戶列表,默認用戶名密碼都爲guest rabbitmqctl add_user admin1 123 # 新增用戶 rabbitmqctl set_user_tags admin1 administrator # 設置用戶admin1爲管理員級別 # 其餘命令 rabbitmqctl add_user <username> <password> rabbitmqctl delete_user <username> rabbitmqctl change_password <username> <newpassword> rabbitmqctl clear_password <username> rabbitmqctl authenticate_user <username> <password> rabbitmqctl set_user_tags <username> <tag> ... rabbitmqctl list_users
# 開啓web可視化界面 rabbitmq-plugins enable rabbitmq_management # 須要重啓rabbitmq service rabbitmq-server restart # 接下來瀏覽器訪問IP:15672便可
rabbitmq從3.3.0開始禁止使用guest/guest權限經過除localhost外的訪問,不然會報錯
須要在
/etc/rabbitmq/rabbitmq.config文件中須要添加
{loopback_users, []}配置:
[{rabbit, [ {loopback_users, []} ]}].
若是節點須要設置成內存節點,則加入集羣的命令以下:
rabbitmqctl join_cluster --ram rabbit@rabbitmq-1 # –ram指的是做爲內存節點,若是不加,那就默認爲內存節點。
若是節點在集羣中已是磁盤節點了,經過如下命令能夠將節點改爲內存節點:
rabbitmqctl stop_app # 中止rabbitmq服務 rabbitmqctl change_cluster_node_type ram # 更改節點爲內存節點 rabbitmqctl start_app # 開啓rabbitmq服務
當節點發生故障時,儘管全部元數據信息均可以從磁盤節點上將元數據拷貝到本節點上,可是隊列的消息內容就不行了,這樣就會致使消息的丟失,那是由於在默認狀況下,隊列只會保存在其中一個節點上,咱們在將集羣隊列時也說過。
聰明的 RabbitMQ 早就意識到這個問題了,在 2.6之後的版本中增長了,隊列冗餘選項:鏡像隊列。鏡像隊列的主隊列(master)依然是僅存在於一個節點上,其他從主隊列拷貝的隊列叫從隊列(slave)。若是主隊列沒有發生故障,那麼其工做流程依然跟普通隊列同樣,生產者和消費者不會感知其變化,當發佈消息時,依然是路由到主隊列中,而主隊列經過相似廣播的機制,將消息擴散同步至其他從隊列中,這就有點像 fanout 交換器同樣。而消費者依然是從主隊列中讀取消息。
一旦主隊列發生故障,集羣就會從最老的一個從隊列選舉爲新的主隊列,這也就實現了隊列的高可用了,但咱們切記不要濫用這個機制,在上面也說了,隊列的冗餘操做會致使不能經過擴展節點增長存儲空間,並且會形成性能瓶頸。
命令格式以下
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority] # -p Vhost: 可選參數,針對指定vhost下的queue進行設置 # Name: policy的名稱 # Pattern: queue的匹配模式(正則表達式) # Definition: 鏡像定義,包括三個部分ha-mode, ha-params, ha-sync-mode # ha-mode: 指明鏡像隊列的模式,有效值爲 all/exactly/nodes # all: 表示在集羣中全部的節點上進行鏡像 # exactly: 表示在指定個數的節點上進行鏡像,節點的個數由ha-params指定 # nodes: 表示在指定的節點上進行鏡像,節點名稱經過ha-params指定 # ha-params: ha-mode模式須要用到的參數 # ha-sync-mode: 進行隊列中消息的同步方式,有效值爲automatic和manual # priority: 可選參數,policy的優先級
如下示例聲明名爲ha-all的策略,它與名稱以」ha」開頭的隊列相匹配,並將鏡像配置到集羣中的全部節點:
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
上述命令會將全部的隊列冗餘到全部節點上,通常能夠拿來測試。
策略的名稱以」two」開始的隊列鏡像到羣集中的任意兩個節點,並進行自動同步:
rabbitmqctl set_policy ha-two "^two." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
以」node」開頭的隊列鏡像到集羣中的特定節點的策略:
rabbitmqctl set_policy ha-nodes "^nodes." '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
HAProxy 提供高可用性、負載均衡以及基於 TCP 和 HTTP 應用的代理,支持虛擬主機,它是免費、快速而且可靠的一種解決方案。
集羣負載均和架構圖:
yum -y install haproxy
vim /etc/haproxy/haproxy.cfg
#綁定配置 listen rabbitmq_cluster 0.0.0.0:5670 #配置TCP模式 mode tcp #加權輪詢 balance roundrobin #RabbitMQ集羣節點配置 server rabbitmq-1 192.168.171.134:5672 check inter 2000 rise 2 fall 3 server rabbitmq-2 192.168.171.135:5672 check inter 2000 rise 2 fall 3 #haproxy監控頁面地址 listen monitor 0.0.0.0:8100 mode http option httplog stats enable stats uri /stats stats refresh 5s
systemctl restart haproxy
瀏覽器訪問IP:8100/stats