以前简单介绍了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等持久化须要在客户端声明指定