以前簡單介紹了CentOS下單機部署RabbltMQ環境的操做記錄,下面詳細說下RabbitMQ集羣知識,RabbitMQ是用erlang開發的,集羣很是方便,由於erlang天生就是一門分佈式語言,但其自己並不支持負載均衡。html
Rabbit集羣模式大概分爲如下三種:單一模式、普通模式、鏡像模式,其中:
1)單一模式:最簡單的狀況,非集羣模式,沒什麼好說的。
2)普通模式:默認的集羣模式。
-> 對於Queue來講,消息實體只存在於其中一個節點,A、B兩個節點僅有相同的元數據,即隊列結構。
-> 當消息進入A節點的Queue中後,consumer從B節點拉取時,RabbitMQ會臨時在A、B間進行消息傳輸,把A中的消息實體取出並通過B發送給consumer。
-> 因此consumer應儘可能鏈接每個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點創建物理Queue。不然不管consumer連A或B,出口總在A,會產生瓶頸。
-> 該模式存在一個問題就是當A節點故障後,B節點沒法取到A節點中還未消費的消息實體。
-> 若是作了消息持久化,那麼得等A節點恢復,而後纔可被消費;若是沒有持久化的話,而後就沒有而後了。
3)鏡像模式:把須要的隊列作成鏡像隊列,存在於多個節點,屬於RabbitMQ的HA方案。
-> 該模式解決了上述問題,其實質和普通模式不一樣之處在於,消息實體會主動在鏡像節點間同步,而不是在consumer取數據時臨時拉取。
-> 該模式帶來的反作用也很明顯,除了下降系統性能外,若是鏡像隊列數量過多,加之大量的消息進入,集羣內部的網絡帶寬將會被這種同步通信大大消耗掉。
-> 因此在對可靠性要求較高的場合中適用於該模式(好比下面圖中介紹該種集羣模式)。node
RabbitMQ集羣中的基本概念:
1)RabbitMQ的集羣節點包括內存節點、磁盤節點。顧名思義內存節點就是將全部數據放在內存,磁盤節點將數據放在磁盤。不過,如前文所述,若是在投遞消息時,打開了消息的持久化,那麼即便是內存節點,數據仍是安全的放在磁盤。
2)一個rabbitmq集 羣中能夠共享 user,vhost,queue,exchange等,全部的數據和狀態都是必須在全部節點上覆制的,一個例外是,那些當前只屬於建立它的節點的消息隊列,儘管它們可見且可被全部節點讀取。rabbitmq節點能夠動態的加入到集羣中,一個節點它能夠加入到集羣中,也能夠從集羣環集羣會進行一個基本的負載均衡。nginx
RabbitMQ集羣中有兩種節點:
1)Ram內存節點:只保存狀態到內存(一個例外的狀況是:持久的queue的持久內容將被保存到disk)
2)Disk磁盤節點:保存狀態到內存和磁盤。
內存節點雖然不寫入磁盤,可是它執行比磁盤節點要好。RabbitMQ集羣中,只須要一個磁盤節點來保存狀態就足夠了;若是集羣中只有內存節點,那麼不能中止它們,不然全部的狀態,消息等都會丟失。web
RabbitMQ集羣思路:
那麼具體如何實現RabbitMQ高可用,咱們先搭建一個普通集羣模式,在這個模式基礎上再配置鏡像模式實現高可用,Rabbit集羣前增長一個反向代理,生產者、消費者經過反向代理訪問RabbitMQ集羣。redis
上圖中3個RabbitMQ運行在同一主機上,分別用不一樣的服務端口。固然在生產環境裏,多個RabbitMQ確定是運行在不一樣的物理服務器上,不然就失去了高可用的意義。api
RabbitMQ集羣模式配置
該設計架構能夠以下:在一個集羣裏,有3臺機器,其中1臺使用磁盤模式,另2臺使用內存模式。2臺內存模式的節點,無疑速度更快,所以客戶端(consumer、producer)鏈接訪問它們。而磁盤模式的節點,因爲磁盤IO相對較慢,所以僅做數據備份使用,另一臺做爲反向代理。安全
配置RabbitMQ集羣很是簡單,只須要幾個命令,以下面範例,簡單說下配置的幾個步驟:
第一步:queue、kevintest一、kevintest2作爲RabbitMQ集羣節點,分別安裝RabbitMq-Server ,安裝後分別啓動RabbitMq-server。bash
1
2
|
啓動命令
# Rabbit-Server start
|
第二步:在安裝好的三臺節點服務器中,分別修改/etc/hosts文件,指定queue、kevintest一、kevintest2的hosts。服務器
1
2
3
4
5
6
|
172.16.3.32 queue
172.16.3.107 kevintest1
172.16.3.108 kevintest2
三臺節點的
hostname
要正確,主機名分別是queue、kevintest一、kevintest2,若是修改
hostname
,建議安裝rabbitmq前修改。請注意RabbitMQ集羣節點必須在同一個網段裏,
若是是跨廣域網效果就差。
|
第三步:設置每一個節點Cookiecookie
1
2
3
4
5
6
7
8
9
10
11
12
|
Rabbitmq的集羣是依賴於erlang的集羣來工做的,因此必須先構建起erlang的集羣環境。Erlang的集羣中各節點是經過一個magic cookie來實現的,這個cookie存放在
/var/lib/rabbitmq/
.erlang.cookie 中,文件是400的權限。因此必須保證各節點cookie保持一致,不然節點之間就沒法通訊。
# ll /var/lib/rabbitmq/.erlang.cookie
-r-------- 1 rabbitmq rabbitmq 21 12月 6 00:40
/var/lib/rabbitmq/
.erlang.cookie
將queue的
/var/lib/rabbitmq/
.erlang.cookie這個文件,拷貝到kevintest一、kevintest2的同一位置(反過來亦可),該文件是集羣節點進行通訊的驗證密鑰,全部
節點必須一致。拷完後重啓下RabbitMQ。複製好後別忘記還原.erlang.cookie的權限,不然可能會遇到錯誤
# chmod 400 /var/lib/rabbitmq/.erlang.cookie
設置好cookie後先將三個節點的rabbitmq重啓
# rabbitmqctl stop
# rabbitmq-server start
|
第四步:中止全部節點RabbitMq服務,而後使用detached參數獨立運行,這步很關鍵,尤爲增長節點中止節點後再次啓動遇到沒法啓動,均可以參照這個順序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
[root@queue ~]
# rabbitmqctl stop
[root@kevintest1 ~]
# rabbitmqctl stop
[root@kevintest2 ~]
# rabbitmqctl stop
[root@queue ~]
# rabbitmq-server -detached
[root@kevintest1 ~]
# rabbitmq-server -detached
[root@kevintest2 ~]
# rabbitmq-server -detached
分別查看下每一個節點
[root@queue ~]
# rabbitmqctl cluster_status
Cluster status of node rabbit@queue ...
[{nodes,[{disc,[rabbit@queue]}]},
{running_nodes,[rabbit@queue]},
{partitions,[]}]
...
done
.
[root@kevintest1 ~]
# rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest1...
[{nodes,[{disc,[rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest1]},
{partitions,[]}]
...
done
.
[root@kevintest2 ~]
# rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest2...
[{nodes,[{disc,[rabbit@kevintest2]}]},
{running_nodes,[rabbit@kevintest2]},
{partitions,[]}]
...
done
.
|
第五步:將kevintest一、kevintest2做爲內存節點與queue鏈接起來,在kevintest1上,執行以下命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@kevintest1 ~]
# rabbitmqctl stop_app
[root@kevintest1 ~]
# rabbitmqctl join_cluster --ram rabbit@queue
[root@kevintest1 ~]
# rabbitmqctl start_app
[root@kevintest2 ~]
# rabbitmqctl stop_app
[root@kevintest2 ~]
# rabbitmqctl join_cluster --ram rabbit@queue #上面已經將kevintest1與queue鏈接,也能夠直接將kevintest2與kevintest1鏈接,一樣而已加入集羣中
[root@kevintest2 ~]
# rabbitmqctl start_app
1)上述命令先停掉rabbitmq應用,而後調用cluster命令,將kevintest1鏈接到,使二者成爲一個集羣,最後重啓rabbitmq應用。
2)在這個cluster命令下,kevintest一、kevintest2是內存節點,queue是磁盤節點(RabbitMQ啓動後,默認是磁盤節點)。
3)queue若是要使kevintest1或kevintest2在集羣裏也是磁盤節點,join_cluster 命令去掉--
ram
參數便可
#rabbitmqctl join_cluster rabbit@queue
只要在節點列表裏包含了本身,它就成爲一個磁盤節點。在RabbitMQ集羣裏,必須至少有一個磁盤節點存在。
|
第六步:在queue、kevintest一、kevintest2上,運行cluster_status命令查看集羣狀態:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# rabbitmqctl cluster_status
Cluster status of node rabbit@queue ...
[{nodes,[{disc,[rabbit@queue]},{
ram
,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest2,rabbit@kevintest1,rabbit@queue]},
{partitions,[]}]
...
done
.
[root@kevintest1 rabbitmq]
# rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest1 ...
[{nodes,[{disc,[rabbit@queue]},{
ram
,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest2,rabbit@queue,rabbit@kevintest1]},
{partitions,[]}]
...
done
.
[root@kevintest2 rabbitmq]
# rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest2 ...
[{nodes,[{disc,[rabbit@queue]},{
ram
,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest1,rabbit@queue,rabbit@kevintest2]},
{partitions,[]}]
...
done
.
這時能夠看到每一個節點的集羣信息,分別有兩個內存節點一個磁盤節點
|
第七步:往任意一臺集羣節點裏寫入消息隊列,會複製到另外一個節點上,咱們看到兩個節點的消息隊列數一致:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[root@kevintest2 ~]
# rabbitmqctl list_queues -p hrsystem
Listing queues …
test_queue 10000
…
done
.
[root@kevintest1 ~]
# rabbitmqctl list_queues -p hrsystem
Listing queues …
test_queue 10000
…
done
.
[root@queue ~]
# rabbitmqctl list_queues -p hrsystem
Listing queues …
test_queue 10000
…
done
.
-p參數爲vhost名稱
|
這樣RabbitMQ集羣就正常工做了,這種模式更適合非持久化隊列,只有該隊列是非持久的,客戶端才能從新鏈接到集羣裏的其餘節點,並從新建立隊列。假如該隊列是持久化的,那麼惟一辦法是將故障節點恢復起來;爲何RabbitMQ不將隊列複製到集羣裏每一個節點呢?這與它的集羣的設計本意相沖突,集羣的設計目的就是增長更多節點時,能線性的增長性能(CPU、內存)和容量(內存、磁盤)。理由以下:固然RabbitMQ新版本集羣也支持隊列複製(有個選項能夠配置)。好比在有五個節點的集羣裏,能夠指定某個隊列的內容在2個節點上進行存儲,從而在性能與高可用性之間取得一個平衡。
=============清理RabbitMQ消息隊列中的全部數據============
1
2
3
4
5
6
|
方法以下:
# rabbitmqctl list_queues //查看全部隊列數據
# rabbitmqctl stop_app //要先關閉應用,不然不能清除
# rabbitmqctl reset
# rabbitmqctl start_app
# rabbitmqctl list_queues //這時候看到listing 及queues都是空的
|
=========================================================================================
RabbitMQ集羣:
1)RabbitMQ broker集羣是多個erlang節點的邏輯組,每一個節點運行rabbitmq應用,他們之間共享用戶、虛擬主機、隊列、exchange、綁定和運行時參數;
2)RabbitMQ集羣之間複製什麼信息:除了message queue(存在一個節點,從其餘節點均可見、訪問該隊列,要實現queue的複製就須要作queue的HA)以外,任何一個rabbitmq broker上的全部操做的data和state都會在全部的節點之間進行復制;
3)RabbitMQ消息隊列是很是基礎的關鍵服務。本文3臺rabbitMQ服務器構建broker集羣,1個master,2個slave。容許2臺服務器故障而服務不受影響。
RabbitMQ集羣的目的
1)容許消費者和生產者在RabbitMQ節點崩潰的狀況下繼續運行
2)經過增長更多的節點來擴展消息通訊的吞吐量
RabbitMQ集羣運行的前提:
1)集羣全部節點必須運行相同的erlang及rabbitmq版本
2)hostname解析,節點之間經過域名相互通訊,本文爲3個node的集羣,採用配置hosts的形式。
RabbitMQ端口及用途
1)5672 客戶端鏈接用途
2)15672 web管理接口
3)25672 集羣通訊用途
RabbitMQ集羣的搭建方式:
1)經過rabbitmqctl手工配置 (本文采用此方式)
2)經過配置文件聲明
3)經過rabbitmq-autocluster插件聲明
4)經過rabbitmq-clusterer插件聲明
RabbitMQ集羣故障處理機制:
1)rabbitmq broker集羣容許個體節點down機,
2)對應集羣的的網絡分區問題( network partitions)
RabbitMQ集羣推薦用於LAN環境,不適用WAN環境;要經過WAN鏈接broker,Shovel or Federation插件是最佳的解決方案;Shovel or Federation不一樣於集羣。
RabbitMQ集羣的節點運行模式:
爲保證數據持久性,目前全部node節點跑在disk模式,若是從此壓力大,須要提升性能,考慮採用ram模式
RabbitMQ節點類型
1)RAM node:內存節點將全部的隊列、交換機、綁定、用戶、權限和vhost的元數據定義存儲在內存中,好處是可使得像交換機和隊列聲明等操做更加的快速。
2)Disk node:將元數據存儲在磁盤中,單節點系統只容許磁盤類型的節點,防止重啓RabbitMQ的時候,丟失系統的配置信息。
問題說明:
RabbitMQ要求在集羣中至少有一個磁盤節點,全部其餘節點能夠是內存節點,當節點加入或者離開集羣時,必需要將該變動通知到至少一個磁盤節點。
若是集羣中惟一的一個磁盤節點崩潰的話,集羣仍然能夠保持運行,可是沒法進行其餘操做(增刪改查),直到節點恢復。
解決方案:設置兩個磁盤節點,至少有一個是可用的,能夠保存元數據的更改。
RabbitMQ集羣節點之間是如何相互認證的:
1)經過Erlang Cookie,至關於共享祕鑰的概念,長度任意,只要全部節點都一致便可。
2)rabbitmq server在啓動的時候,erlang VM會自動建立一個隨機的cookie文件。cookie文件的位置是/var/lib/rabbitmq/.erlang.cookie 或者 /root/.erlang.cookie,爲保證cookie的徹底一致,採用從一個節點copy的方式。
Erlang Cookie是保證不一樣節點能夠相互通訊的密鑰,要保證集羣中的不一樣節點相互通訊必須共享相同的Erlang Cookie。具體的目錄存放在/var/lib/rabbitmq/.erlang.cookie。
說明:這就要從rabbitmqctl命令的工做原理提及,RabbitMQ底層是經過Erlang架構來實現的,因此rabbitmqctl會啓動Erlang節點,並基於Erlang節點來使用Erlang系統鏈接RabbitMQ節點,在鏈接過程當中須要正確的Erlang Cookie和節點名稱,Erlang節點經過交換Erlang Cookie以得到認證。
=======如下記錄CentOS6.9下RabbitMQ集羣部署過程=======
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
集羣機器信息:
rabbitmq01.kevin.cn 192.168.1.40
rabbitmq02.kevin.cn 192.168.1.41
rabbitmq03.kevin.cn 192.168.1.42
1)設置hosts主機解析,rabbitmq 集羣通訊用途,全部節點配置相同。
[root@rabbitmq01 ~]
# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.40 rabbitmq01.kevin.cn
192.168.1.41 rabbitmq02.kevin.cn
192.168.1.42 rabbitmq03.kevin.cn
其餘兩個節點的hosts配置一致。
2)三臺節點服務器上都要部署rabbitmq環境,能夠參考:http:
//www
.cnblogs.com
/kevingrace/p/7693042
.html
前臺運行rabbitmq服務:
# /etc/init.d/rabbitmq-server start (用戶關閉鏈接後,自動結束進程)
或者
# rabbitmq-server start
設置開機啓動
# chkconfig rabbitmq-server on
後臺運行rabbitmq服務:
# rabbitmq-server -detached
# lsof -i:5672
# lsof -i:15672
# lsof -i:25672
查看各節點狀態:
# rabbitmqctl status
或者
# /etc/init.d/rabbitmq-server status
3)設置節點間認證的cookie。能夠把其中一個節點(好比rabbitmq01)的文件使用
scp
拷貝到其餘兩個節點上
[root@rabbitmq01 ~]
# cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
[root@rabbitmq02 ~]
# cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
[root@rabbitmq03 ~]
# cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
同步完cookie以後,重啓rabbitmq-server。
# /etc/init.d/rabbitmq-server restart
4)爲了把集羣中的3個節點聯繫起來,能夠將其中兩個節點加入到另外一個節點中。
好比:將rabbitmq0一、rabbitmq03分別加入到集羣rabbitmq02中,其中rabbitmq01和rabbitmq02節點爲內存節點。rabbitmq02爲磁盤節點。
注意:rabbitmqctl stop_app ---僅關閉應用,節點不被關閉
[root@rabbitmq01 ~]
# rabbitmqctl stop_app
[root@rabbitmq01 ~]
# rabbitmqctl join_cluster --ram rabbit@rabbitmq02
[root@rabbitmq01 ~]
# rabbitmqctl start_app
[root@rabbitmq03 ~]
# rabbitmqctl stop_app
[root@rabbitmq03 ~]
# rabbitmqctl join_cluster --ram rabbit@rabbitmq02
[root@rabbitmq03 ~]
# rabbitmqctl start_app
查看RabbitMQ集羣狀況(三個節點查看的結果同樣)
[root@rabbitmq01 ~]
# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq01 ...
[{nodes,[{disc,[rabbit@rabbitmq02]},
{
ram
,[rabbit@rabbitmq03,rabbit@rabbitmq01]}]},
{running_nodes,[rabbit@rabbitmq03,rabbit@rabbitmq02,rabbit@rabbitmq01]},
{cluster_name,<<
"rabbit@rabbitmq02.kevin.cn"
>>},
{partitions,[]},
{alarms,[{rabbit@rabbitmq03,[]},
{rabbit@rabbitmq02,[]},
{rabbit@rabbitmq01,[]}]}]
RabbitMQ集羣的名字默認是第一個節點的名字,好比上面集羣的名字是rabbitmq01。
修改RabbitMQ集羣的名字kevinmq
# rabbitmqctl set_cluster_name kevinmq
# rabbitmqctl cluster_status
重啓集羣:
# rabbitmqctl stop
# rabbitmq-server -detached
# rabbitmqctl cluster_status //觀察集羣的運行狀態變化
5)重要信息:
當整個集羣down掉時,最後一個down機的節點必須第一個啓動到在線狀態,若是不是這樣,節點會等待30s等最後的磁盤節點恢復狀態,而後失敗。
若是最後下線的節點不能上線,能夠經過forget_cluster_node 指令來踢出集羣。
若是全部的節點不受控制的同時宕機,好比掉電,會進入全部的節點都會認爲其餘節點比本身宕機的要晚,即本身先宕機,這種狀況下可使用
force_boot指令來啓動一個節點。
6)打破集羣:
當一個節點不屬於這個集羣的時候,須要及時踢出,能夠經過本地或者遠程的方式
# rabbitmqctl stop_app
# rabbitmqctl reset
# rabbitmqctl start_app
這樣再次查看RabbitMQ集羣的時候,該節點就不會在這裏面了
# rabbitmqctl cluster_status
7)客戶端鏈接集羣測試
經過web管理頁面進行建立隊列、發佈消息、建立用戶、建立policy等。
http:
//192
.168.1.41:15672/
或者經過rabbitmqadmin命令行來測試
[root@rabbitmq02 ~]
# wget https://192.168.1.41:15672/cli/rabbitmqadmin
[root@rabbitmq02 ~]
# chmod +x rabbitmqadmin
[root@rabbitmq02 ~]
# mv rabbitmqadmin /usr/sbin/
Declare an exchange
[root@rabbitmq02 ~]
# rabbitmqadmin declare exchange name=my-new-exchange type=fanout
exchange declared
Declare a queue, with optional parameters
[root@rabbitmq02 ~]
# rabbitmqadmin declare queue name=my-new-queue durable=false
queue declared
Publish a message
[root@rabbitmq02 ~]
# rabbitmqadmin publish exchange=my-new-exchange routing_key=test payload="hello, world"
Message published
And get it back
[root@rabbitmq02 ~]
# rabbitmqadmin get queue=test requeue=false
+-------------+----------+---------------+--------------+------------------+-------------+
| routing_key | exchange | message_count | payload | payload_encoding | redelivered |
+-------------+----------+---------------+--------------+------------------+-------------+
|
test
| | 0 | hello, world | string | False |
+-------------+----------+---------------+--------------+------------------+-------------+
|
測試後發現問題問題:
[root@rabbitmq01 ~]# rabbitmqctl stop_app
[root@rabbitmq01 ~]# rabbitmqctl stop
在stop_app或者stop掉broker以後在rabbitmq01節點的上隊列已經不可用了,重啓rabbitmq01的app或broker以後,雖然集羣工做正常,但rabbitmq01上隊列中消息會被清空(queue仍是存在的)
對於生產環境而已,這確定是不可接受的,若是不能保證隊列的高可用,那麼作集羣的意義也不太大了,還好rabbitmq支持Highly Available Queues,下面介紹下queue的HA。
=================Queue HA配置===============
默認狀況下,RabbitMQ集羣中的隊列存在於集羣中的單個節點上,這要看建立隊列時聲明在那個節點上建立,而exchange和binding則默認存在於集羣中全部節點。
隊列能夠經過鏡像來提升可用性,HA依賴rabbitmq cluster,因此隊列鏡像也不適合WAN部署,每一個被鏡像的隊列包含一個master和一個或者多個slave,當master
因任何緣由故障時,最老的slave被提高爲新的master。發佈到隊列的消息被複制到全部的slave上,消費者不管鏈接那個node,都會鏈接到master;若是master確
認要刪除消息,那麼全部slave就會刪除隊列中消息。隊列鏡像能夠提供queue的高可用性,但不能分擔負載,由於全部參加的節點都作全部的工做。
1. 配置隊列鏡像
經過policy來配置鏡像,策略可在任什麼時候候建立,好比先建立一個非鏡像的隊列,而後在鏡像,反之亦然。
鏡像隊列和非鏡像隊列的區別是非鏡像隊列沒有slaves,運行速度也比鏡像隊列快。
設置策略,而後設置ha-mode,3種模式:all、exactly、nodes。
每一個隊列都有一個home node,叫作queue master node
1)設置policy,以ha.開頭的隊列將會被鏡像到集羣其餘全部節點,一個節點掛掉而後重啓後須要手動同步隊列消息
1
|
# rabbitmqctl set_policy ha-all-queue "^ha\." '{"ha-mode":"all"}'
|
2)設置policy,以ha.開頭的隊列將會被鏡像到集羣其餘全部節點,一個節點掛掉而後重啓後會自動同步隊列消息(生產環境採用這個方式)
1
|
# rabbitmqctl set_policy ha-all-queue "^ha\." '{"ha-mode":"all","ha-sync-mode":"automatic"}'
|
2. 問題:
配置鏡像隊列後,其中1臺節點失敗,隊列內容是不會丟失,若是整個集羣重啓,隊列中的消息內容仍然丟失,如何實現隊列消息內容持久化那?
集羣節點跑在disk模式,建立見消息的時候也聲明瞭持久化,爲何仍是不行那?
由於建立消息的時候須要指定消息是否持久化,若是啓用了消息的持久化的話,重啓集羣消息也不會丟失了,前提是建立的隊列也應該是建立的持久化隊列。
客戶端鏈接rabbitMQ集羣服務的方式:
1)客戶端能夠鏈接集羣中的任意一個節點,若是一個節點故障,客戶端自行從新鏈接到其餘的可用節點;(不推薦,對客戶端不透明)
2)經過動態DNS,較短的ttl
3)經過HA+4層負載均衡器(好比haproxy+keepalived)
==========Haproxy+keepalived的部署===============
消息隊列做爲公司的關鍵基礎服務,爲給客戶端提供穩定、透明的rabbitmq服務,現經過Haproxy+keepalived構建高可用的rabbitmq統一入口,及基本的負載均衡服務。
爲簡化安裝配置,現採用yum的方式安裝haproxy和keepalived,可參考 基於keepalived+nginx部署強健的高可用7層負載均衡方案。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
|
在兩臺兩臺服務器部署haproxy+Keepalived環境,部署過程同樣。
haroxy01.kevin.cn 192.168.1.43
haroxy02.kevin.cn 192.168.1.44
1)安裝
[root@haproxy01 ~]
# yum install haproxy keepalived -y
[root@haproxy01 ~]
# /etc/init.d/keepalived start
2)設置關鍵服務開機自啓動
[root@haproxy01 ~]
# chkconfig --list|grep haproxy
[root@haproxy01 ~]
# chkconfig haproxy on
[root@haproxy01 ~]
# chkconfig --list|grep haproxy
3) 配置將haproxy的log記錄到
/var/log/haproxy
.log
[root@haproxy01 ~]
# more /etc/rsyslog.d/haproxy.conf
$ModLoad imudp
$UDPServerRun 514
local0.*
/var/log/haproxy
.log
[root@haproxy01 ~]
# /etc/init.d/rsyslog restart
4)haproxy的配置,2臺機器上的配置徹底相同
[root@haproxy01 ~]
# more /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 notice
chroot
/var/lib/haproxy
pidfile
/var/run/haproxy
.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket
/var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode tcp
option tcplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
###haproxy statistics monitor by laijingli 20160222
listen statics 0.0.0.0:8888
mode http
log 127.0.0.1 local0 debug
transparent
stats refresh 60s
stats uri / haproxy-stats
stats realm Haproxy \ statistic
stats auth laijingli:xxxxx
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend kevin_rabbitMQ_cluster_frontend
mode tcp
option tcpka
log 127.0.0.1 local0 debug
bind 0.0.0.0:5672
use_backend kevin_rabbitMQ_cluster_backend
frontend kevin_rabbitMQ_cluster_management_frontend
mode tcp
option tcpka
log 127.0.0.1 local0 debug
bind 0.0.0.0:15672
use_backend kevin_rabbitMQ_cluster_management_backend
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kevin_rabbitMQ_cluster_backend
balance roundrobin
server rabbitmq01.kevin.cn 192.168.1.40:5672 check inter 3s rise 1 fall 2
server rabbitmq02.kevin.cn 192.168.1.41:5672 check inter 3s rise 1 fall 2
server rabbitmq03.kevin.cn 192.168.1.42:5672 check inter 3s rise 1 fall 2
backend kevin_rabbitMQ_cluster_management_backend
balance roundrobin
server rabbitmq01.kevin.cn 192.168.1.40:15672 check inter 3s rise 1 fall 2
server rabbitmq02.kevin.cn 192.168.1.41:15672 check inter 3s rise 1 fall 2
server rabbitmq03.kevin.cn 192.168.1.42:15672 check inter 3s rise 1 fall 2
5)keepalived配置,特別注意2臺服務器上的keepalived配置不同。
=======================先看下haroxy01.kevin.cn機器上的配置===========================
[root@haproxy01 ~]
# more /etc/keepalived/keepalived.conf
global_defs {
notification_email {
wangshibo@kevin.cn
102533678@qq.com
}
notification_email_from notice@kevin.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy43
## xxhaproxy101 on master , xxhaproxy102 on backup
}
###simple check with killall -0 which is less expensive than pidof to verify that nginx is running
vrrp_script chk_nginx {
script
"killall -0 nginx"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance KEVIN_GATEWAY {
state MASTER
## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 101
## KEVIN_GATEWAY virtual_router_id
priority 200
## 200 on master , 199 on backup
advert_int 1
###採用單播通訊,避免同一個局域網中多個keepalived組之間的相互影響
unicast_src_ip 192.168.1.43
##本機ip
unicast_peer {
192.168.1.44
##對端ip
}
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.1.45
## VIP
}
###若是隻有一塊網卡的話監控網絡接口就沒有必要了
#track_interface {
# em1
#}
track_script {
chk_nginx
}
###狀態切換是發送郵件通知,本機記錄log,後期會觸發短信通知
notify_master
/usr/local/bin/keepalived_notify
.sh notify_master
notify_backup
/usr/local/bin/keepalived_notify
.sh notify_backup
notify_fault
/usr/local/bin/keepalived_notify
.sh notify_fault
notify
/usr/local/bin/keepalived_notify
.sh notify
smtp_alert
}
###simple check with killall -0 which is less expensive than pidof to verify that haproxy is running
vrrp_script chk_haproxy {
script
"killall -0 haproxy"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance kevin_rabbitMQ_GATEWAY {
state BACKUP
## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 111
## kevin_rabbitMQ_GATEWAY virtual_router_id
priority 199
## 200 on master , 199 on backup
advert_int 1
###採用單播通訊,避免同一個局域網中多個keepalived組之間的相互影響
unicast_src_ip 192.168.1.43
##本機ip
unicast_peer {
192.168.1.44
##對端ip
}
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.1.46
## VIP
}
###若是隻有一塊網卡的話監控網絡接口就沒有必要了
#track_interface {
# em1
#}
track_script {
chk_haproxy
}
###狀態切換是發送郵件通知,本機記錄log,後期會觸發短信通知
notify_master
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_master
notify_backup
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_backup
notify_fault
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_fault
notify
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify
smtp_alert
}
=============================再看下haroxy02.kevin.cn機器上的配置==========================
[root@haproxy02 ~]
# more /etc/keepalived/keepalived.conf
global_defs {
notification_email {
wangshibo@kevin.cn
102533678@qq.com
}
notification_email_from notice@kevin.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy44
## xxhaproxy101 on master , xxhaproxy102 on backup
}
###simple check with killall -0 which is less expensive than pidof to verify that nginx is running
vrrp_script chk_nginx {
script
"killall -0 nginx"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance KEVIN_GATEWAY {
state BACKUP
## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 101
## KEVIN_GATEWAY virtual_router_id
priority 199
## 200 on master , 199 on backup
advert_int 1
###採用單播通訊,避免同一個局域網中多個keepalived組之間的相互影響
unicast_src_ip 192.168.1.44
##本機ip
unicast_peer {
192.168.1.43
##對端ip
}
authentication {
auth_type PASS
auth_pass YN_API_HA_PASS
}
virtual_ipaddress {
192.168.1.45
## VIP
}
###若是隻有一塊網卡的話監控網絡接口就沒有必要了
#track_interface {
# em1
#}
track_script {
chk_nginx
}
###狀態切換是發送郵件通知,本機記錄log,後期會觸發短信通知
notify_master
/usr/local/bin/keepalived_notify
.sh notify_master
notify_backup
/usr/local/bin/keepalived_notify
.sh notify_backup
notify_fault
/usr/local/bin/keepalived_notify
.sh notify_fault
notify
/usr/local/bin/keepalived_notify
.sh notify
smtp_alert
}
###simple check with killall -0 which is less expensive than pidof to verify that haproxy is running
vrrp_script chk_haproxy {
script
"killall -0 haproxy"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance kevin_rabbitMQ_GATEWAY {
state MASTER
## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 111
## kevin_rabbitMQ_GATEWAY virtual_router_id
priority 200
## 200 on master , 199 on backup
advert_int 1
###採用單播通訊,避免同一個局域網中多個keepalived組之間的相互影響
unicast_src_ip 192.168.1.44
##本機ip
unicast_peer {
192.168.1.43
##對端ip
}
authentication {
auth_type PASS
auth_pass YN_MQ_HA_PASS
}
virtual_ipaddress {
192.168.1.46
## VIP
}
###若是隻有一塊網卡的話監控網絡接口就沒有必要了
#track_interface {
# em1
#}
track_script {
chk_haproxy
}
###狀態切換是發送郵件通知,本機記錄log,後期會觸發短信通知
notify_master
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_master
notify_backup
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_backup
notify_fault
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify_fault
notify
/usr/local/bin/keepalived_notify_for_haproxy
.sh notify
smtp_alert
}
配置中用到的通知腳本,2臺haproxy服務器上徹底同樣:
[root@haproxy01 ~]
# more /usr/local/bin/keepalived_notify.sh
#!/bin/bash
###keepalived notify script for record ha state transtion to log files
###將將狀態轉換過程記錄到log,便於排錯
logfile=
/var/log/keepalived
.notify.log
echo
--------------- >> $logfile
echo
`
date
` [`
hostname
`] keepalived HA role state transition: $1 $2 $3 $4 $5 $6 >> $logfile
###將狀態轉換記錄到nginx的文件,便於經過web查看ha狀態(必定注意不要開放到公網)
echo
`
date
` `
hostname
` $1 $2 $3 $4 $5 $6 "
" >
/usr/share/nginx/html/index_for_nginx
.html
###將nginx api和rabbitmq的ha log記錄到同一個文件裏
cat
/usr/share/nginx/html/index_for
* >
/usr/share/nginx/html/index
.html
6)haproxy監控頁面。
訪問地址http:
//192
.168.1.43:8888
7)查看keepalived中高可用服務運行在那臺服務器上
https:
//192
.168.1.43
8)經過VIP訪問rabbitMQ服務
http:
//192
.168.1.46:5672
9)其餘問題
rabbitmq服務客戶端使用規範
1)使用vhost來隔離不一樣的應用、不一樣的用戶、不一樣的業務組
2)消息持久化,exchange、queue、message等持久化須要在客戶端聲明指定
|