目錄
1、基本概念
1.1、RabbitMQ集群概述
通過 Erlang 的分布式特性(通過 magic cookie 認證節點)進行 RabbitMQ 集群,各 RabbitMQ 服務為對等節點,即每個節點都提供服務給客戶端連接,進行消息發送與接收。
這些節點通過 RabbitMQ HA 隊列(鏡像隊列)進行消息隊列結構復制。本方案中搭建 3 個節點,並且都是磁盤節點(所有節點狀態保持一致,節點完全對等),只要有任何一個節點能夠工作,RabbitMQ 集群對外就能提供服務。
1.2、軟件負載均衡器HAProxy
HAProxy提供高可用性、負載均衡以及基於TCP和HTTP應用的代理,支持虛擬主機,它是免費、快速並且可靠的一種解決方案。根據官方數據,其最高極限支持10G的並發。HAProxy支持從4層至7層的網絡交換,即覆蓋所有的TCP協議。就是說,Haproxy 甚至還支持 Mysql 的均衡負載。
HAProxy的特點是:
1、HAProxy是支持虛擬主機的,,並能支持上萬級別的連接;
2、能夠補充Nginx的一些缺點比如Session的保持,cookie的引導等工作;
3、支持url檢測后端的服務器出問題的檢測會有很好的幫助;
4、它跟LVS一樣,本身僅僅就只是一款負載均衡軟件;單純從效率上來講HAProxy更會比Nginx有更出色的負載均衡速度,在並發處理上也是優於Nginx的;
5、HAProxy可以對mysql讀進行負載均衡,對后端的MySQL節點進行檢測和負載均衡,不過在后端的MySQL slaves數量超過10台時性能不如LVS,所以我向大家推薦LVS+Keepalived;
6、能夠提供4層,7層代理。HAProxy支持兩種主要的代理模式:"tcp"也即4層(大多用於郵件服務器、內部協議通信服務器等),和7層(HTTP)。在4層模式 下,HAProxy僅在客戶端和服務器之間轉發雙向流量,7層模式下,HAProxy會分析協議,並且能通過允許、拒絕、交換、增加、修改或者刪除請求 (request)或者回應(response)里指定內容來控制協議,這種操作要基於特定規則;
7、HAProxy的算法現在也越來越多了,具體有如下8種:
①roundrobin,表示簡單的輪詢,這個不多說,這個是負載均衡基本都具備的;
②static-rr,表示根據權重,建議關注;
③leastconn,表示最少連接者先處理,建議關注;
④source,表示根據請求源IP,這個跟Nginx的IP_hash機制類似,我們用其作為解決session問題的一種方法,建議關注;
⑤ri,表示根據請求的URI;
⑥rl_param,表示根據請求的URl參數'balance url_param' requires an URL parameter name;
⑦hdr(name),表示根據HTTP請求頭來鎖定每一次HTTP請求;
⑧rdp-cookie(name),表示根據據cookie(name)來鎖定並哈希每一次TCP請求。
2、RabbitMQ的配置步驟
2.1、安裝 Erlang、RabbitMQ
參考文章Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳實踐
2.2、修改 /etc/hosts
加入集群 3 個節點的對應關系:
192.168.0.31 node1
192.168.0.32 node2
192.168.0.33 node3
2.2、設置 Erlang Cookie
RabbitMQ節點之間和命令行工具 (e.g. rabbitmqctl)是使用Cookie互通的,Cookie是一組隨機的數字+字母的字符串。當RabbitMQ服務器啟動的時候,Erlang VM會自動創建一個隨機內容的Cookie文件。如果是通過源安裝RabbitMQ的話,Erlang Cookie 文件在/var/lib/rabbitmq/.erlang.cookie。如果是通過源碼安裝的RabbitMQ,Erlang Cookie文件$HOME/.erlang.cookie。
本文演示的實例是用源碼安裝,由於這個文件權限是 400,所以需要先修改 node2、node3 中的該文件權限為 777:
lion@node1:~$ chmod 777 .erlang.cookie
然后將文件復制到node2、node3上面。
node2:
lion@node2:~$ chmod 777 .erlang.cookie
lion@node2:~$ scp -r node1:/home/lion/.erlang.cookie ~/
lion@node1's password:
.erlang.cookie 100% 20 0.0KB/s 00:00
node3:
lion@node3:~$ chmod 777 .erlang.cookie
lion@node3:~$ scp -r node1:/home/lion/.erlang.cookie ~/
lion@node1's password:
.erlang.cookie 100% 20 0.0KB/s 00:00
分別在node1、node2、node3將權限恢復過來:
lion@node1:~$ chmod 400 .erlang.cookie
最后分別在確認三台機器上的.erlang.cookie的值是一致的
lion@node1:~$ cat .erlang.cookie
VORMVSAAOFOFEQKTNWBA
lion@node2:~$ cat .erlang.cookie
VORMVSAAOFOFEQKTNWBA
lion@node3:~$ cat .erlang.cookie
VORMVSAAOFOFEQKTNWBA
2.3、使用detached參數,在后台啟動Rabbit Node
要先停止現有的Rabbitmq-server,再重新在后台支行
lion@node1:~$ rabbitmqctl stop
Stopping and halting node rabbit@node1 ...
Gracefully halting Erlang VM
lion@node1:~$ rabbitmq-server -detached
通過rabbitmqctl cluster_status命令,可以查看和個節點的狀態,節點的名稱是rabbit@shorthostname,
node1:
lion@node1:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node1 ...
[{nodes,[{disc,[rabbit@node1]}]},
{running_nodes,[rabbit@node1]},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]},
{alarms,[{rabbit@node1,[]}]}]
node2:
lion@node2:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node2 ...
[{nodes,[{disc,[rabbit@node2]}]},
{running_nodes,[rabbit@node2]},
{cluster_name,<<"rabbit@node2">>},
{partitions,[]},
{alarms,[{rabbit@node2,[]}]}]
node3:
lion@node3:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node3 ...
[{nodes,[{disc,[rabbit@node3]}]},
{running_nodes,[rabbit@node3]},
{cluster_name,<<"rabbit@node3">>},
{partitions,[]},
{alarms,[{rabbit@node3,[]}]}]
2.4、將node1、node2、node3組成集群
因為rabbitmq-server啟動時,會一起啟動節點和應用,它預先設置RabbitMQ應用為standalone模式。要將一個節點加入到現有的集群中,你需要停止這個應用並將節點設置為原始狀態,然后就為加入集群准備好了。如果使用./rabbitmqctl stop,應用和節點都將被關閉。所以使用rabbitmqctl stop_app僅僅關閉應用。
node2:
lion@node2:~$ rabbitmqctl stop_app
Stopping node rabbit@node2 ...
lion@node2:~$ rabbitmqctl join_cluster rabbit@node1
Clustering node rabbit@node2 with rabbit@node1 ...
lion@node2:~$ rabbitmqctl start_app
Starting node rabbit@node2 ...
node3:
lion@node3:~$ rabbitmqctl stop_app
Stopping node rabbit@node3 ...
lion@node3:~$ rabbitmqctl join_cluster rabbit@node1
Clustering node rabbit@node3 with rabbit@node1 ...
lion@node3:~$ rabbitmqctl start_app
Starting node rabbit@node3 ...
此時 node2 與 node3 也會自動建立連接。
如果要使用內存節點,則可以使用以下命令:
lion@node2:~$ rabbitmqctl join_cluster --ram rabbit@node1
集群配置好后,可以在 RabbitMQ 任意節點上執行 rabbitmqctl cluster_status 來查看是否集群配置成功。
node1:
lion@node1:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node1 ...
[{nodes,[{disc,[rabbit@node1,rabbit@node2,rabbit@node3]}]},
{running_nodes,[rabbit@node1]},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]},
{alarms,[{rabbit@node1,[]}]}]
node2:
lion@node2:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node2 ...
[{nodes,[{disc,[rabbit@node1,rabbit@node2]}]},{alarms,[{rabbit@node1,[]}]}]
node3:
lion@node3:~$ rabbitmqctl cluster_status
Cluster status of node rabbit@node3 ...
[{nodes,[{disc,[rabbit@node1,rabbit@node2,rabbit@node3]}]},
{alarms,[{rabbit@node1,[]}]}]
同時在Web管理工具中也可以看到效果
2.5、RabbitMQ鏡像功能
使用Rabbit鏡像功能,需要基於RabbitMQ策略來實現,策略是用來控制和修改群集范圍的某個vhost隊列行為和Exchange行為
lion@node2:~$ rabbitmqctl set_policy -p hrsystem ha-allqueue"^" '{"ha-mode":"all"}'
這行命令在vhost名稱為hrsystem創建了一個策略,策略名稱為ha-allqueue,策略模式為 all 即復制到所有節點,包含新增節點,策略正則表達式為 “^” 表示所有匹配所有隊列名稱。
例如下面的命令,^message 這個規則要根據自己修改,這個是指同步"message"開頭的隊列名稱,我們配置時使用的應用於所有隊列,所以表達式為"^"。
lion@node2:~$ rabbitmqctl set_policy -p hrsystem ha-allqueue "^message" '{"ha-mode":"all"}'
更多set_policy說明:http://www.rabbitmq.com/man/rabbitmqctl.1.man.html
2.6、安裝軟件負載均衡器HAProxy1.6
由於Ubuntu的快速發展,官方的源可能不是最新的版本,大多數時候安裝可能是1.4.24,可以通過以下命令,查詢官方提供的版本號:
lion@node4:~$ sudo apt-cache showpkg haproxy
node4是一台新的機器 ,IP地址是192.168.0.34
在寫本文的時候,官方包是沒有1.6版本的,我們可以通過以下命令來安裝 :
lion@node4:~$ sudo add-apt-repository ppa:vbernat/haproxy-1.6
lion@node4:~$ sudo apt-get update
lion@node4:~$ sudo apt-get install haproxy
安裝完以后,可以通過以下命令,查看安裝的版本
lion@node4:~$ haproxy -v
HA-Proxy version 1.6.7 2016/07/13
Copyright 2000-2016 Willy Tarreau <willy@haproxy.org>
安裝完以后,配置文件的目錄在/etc/haproxy/haproxy.cfg,以下是我修改后的配置文件
###########全局配置#########
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy # 改變當前工作目錄
stats socket /run/haproxy/admin.sock mode 660 level admin # 創建監控所用的套接字目錄
pidfile /var/run/haproxy.pid # haproxy的pid存放路徑,啟動進程的用戶必須有權限訪問此文件
maxconn 4000 # 最大連接數,默認4000
user haproxy # 默認用戶
group haproxy # 默認用戶組
daemon # 創建1個進程進入deamon模式運行。此參數要求將運行模式設置為"daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
###########默認配置#########
defaults
log global
mode http # 默認的模式mode { tcp|http|health },tcp是4層,http是7層,health只會返回OK
option httplog # 采用http日志格式
option dontlognull # 啟用該項,日志中將不會記錄空連接。所謂空連接就是在上游的負載均衡器
# 或者監控系統為了探測該 服務是否存活可用時,需要定期的連接或者獲取某
# 一固定的組件或頁面,或者探測掃描端口是否在監聽或開放等動作被稱為空連接;
# 官方文檔中標注,如果該服務上游沒有其他的負載均衡器的話,建議不要使用
# 該參數,因為互聯網上的惡意掃描或其他動作就不會被記錄下來
timeout connect 5000 # 連接超時時間
timeout client 50000 # 客戶端連接超時時間
timeout server 50000 # 服務器端連接超時時間
option httpclose # 每次請求完畢后主動關閉http通道
option httplog # 日志類別http日志格式
#option forwardfor # 如果后端服務器需要獲得客戶端真實ip需要配置的參數,可以從Http Header中獲得客戶端ip
option redispatch # serverId對應的服務器掛掉后,強制定向到其他健康的服務器
timeout connect 10000 # default 10 second timeout if a backend is not found
maxconn 60000 # 最大連接數
retries 3 # 3次連接失敗就認為服務不可用,也可以通過后面設置
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
####################################################################
listen http_front
bind 0.0.0.0:1080 #監聽端口
stats refresh 30s #統計頁面自動刷新時間
stats uri /haproxy?stats #統計頁面url
stats realm Haproxy Manager #統計頁面密碼框上提示文本
stats auth admin:admin #統計頁面用戶名和密碼設置
#stats hide-version #隱藏統計頁面上HAProxy的版本信息
#####################我把RabbitMQ的管理界面也放在HAProxy后面了###############################
listen rabbitmq_admin
bind 0.0.0.0:8004
server node1 192.168.0.31:15672
server node2 192.168.0.32:15672
server node3 192.168.0.33:15672
####################################################################
listen rabbitmq_cluster
bind 0.0.0.0:5672
option tcplog
mode tcp
timeout client 3h
timeout server 3h
option clitcpka
balance roundrobin #負載均衡算法(#banlance roundrobin 輪詢,balance source 保存session值,支持static-rr,leastconn,first,uri等參數)
#balance url_param userid
#balance url_param session_id check_post 64
#balance hdr(User-Agent)
#balance hdr(host)
#balance hdr(Host) use_domain_only
#balance rdp-cookie
#balance leastconn
#balance source //ip
server node1 192.168.0.31:5672 check inter 5s rise 2 fall 3 #check inter 2000 是檢測心跳頻率,rise 2是2次正確認為服務器可用,fall 3是3次失敗認為服務器不可用
server node2 192.168.0.32:5672 check inter 5s rise 2 fall 3
server node3 192.168.0.33:5672 check inter 5s rise 2 fall 3
更多Haproxy的配置文件介紹參考:http://www.haproxy.org/download/1.4/doc/configuration.txt
重新啟動HAProxy
lion@node4:~$ sudo service haproxy restart
* Restarting haproxy haproxy [ OK ]
然后用瀏覽器輸入http://
2.7、測試結果 ,向HAProxy發送消息
使用Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳實踐中的代碼來發送消息, 在node3上我們將消息發送到node4(192.168.0.34)上
原來默認的guest用戶是禁止遠程訪問的,如果要使用lion帳號訪問,需要在web管理控制台中開啟lion對Virtual Host訪問
Console1(node3):
lion@node3:~/_code/_rabbitmq/_golang$ go run producer_hello.go
2016/07/29 12:46:50 dialing "amqp://lion:123456@192.168.0.34:5672/"
2016/07/29 12:46:50 got Connection, getting Channel
2016/07/29 12:46:50 got queue, declaring "test-idoall-queues"
2016/07/29 12:46:50 declared queue, publishing 16B body ("hello idoall.org")
2016/07/29 12:46:50 published 16B OK
Console(node1):
lion@node1:~/_code/_rabbitmq/_golang$ go run consumer_hello.go
2016/07/25 17:37:12 dialing "amqp://guest:guest@localhost:5672/"
2016/07/25 17:37:12 got Connection, getting Channel
2016/07/25 17:37:12 got queue, declaring "test-idoall-queues"
2016/07/25 17:37:12 Queue bound to Exchange, starting Consume
2016/07/25 17:37:12 [*] Waiting for messages. To exit press CTRL+C
2016/07/25 17:37:12 Received a message: hello idoall.org
在上面的代碼中,我們可以看到在node3是向192.168.0.34這台HAProxy上發送消息,然后在node1上可以正常接收。
3、參考閱讀
How to Install HAProxy Load Balancer on Ubuntu
http://www.rabbitmq.com/clustering.html
Can't access RabbitMQ web management interface after fresh install
博文作者:迦壹 博客地址:[RabbitMQ3.6.3集群搭建+HAProxy1.6做負載均衡](http://idoall.org/blog/post/lion/15) 轉載聲明:可以轉載, 但必須以超鏈接形式標明文章原始出處和作者信息及版權聲明,謝謝合作!