以前簡單介紹了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
啓動命令 # Rabbit-Server start
第二步:在安裝好的三臺節點服務器中,分別修改/etc/hosts文件,指定queue、kevintest一、kevintest2的hosts。服務器
172.16.3.32 queue 172.16.3.107 kevintest1 172.16.3.108 kevintest2 三臺節點的hostname要正確,主機名分別是queue、kevintest一、kevintest2,若是修改hostname,建議安裝rabbitmq前修改。請注意RabbitMQ集羣節點必須在同一個網段裏, 若是是跨廣域網效果就差。
第三步:設置每一個節點Cookiecookie
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參數獨立運行,這步很關鍵,尤爲增長節點中止節點後再次啓動遇到沒法啓動,均可以參照這個順序
[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上,執行以下命令:
[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命令查看集羣狀態:
# 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. 這時能夠看到每一個節點的集羣信息,分別有兩個內存節點一個磁盤節點
第七步:往任意一臺集羣節點裏寫入消息隊列,會複製到另外一個節點上,咱們看到兩個節點的消息隊列數一致:
[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消息隊列中的全部數據============
方法以下: # 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集羣部署過程=======
集羣機器信息: 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.開頭的隊列將會被鏡像到集羣其餘全部節點,一個節點掛掉而後重啓後須要手動同步隊列消息
# rabbitmqctl set_policy ha-all-queue "^ha\." '{"ha-mode":"all"}'
2)設置policy,以ha.開頭的隊列將會被鏡像到集羣其餘全部節點,一個節點掛掉而後重啓後會自動同步隊列消息(生產環境採用這個方式)
# 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層負載均衡方案。
在兩臺兩臺服務器部署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等持久化須要在客戶端聲明指定