需求背景
1.业务按需求将一些功能拆分成异步任务,将消息放入队列进行处理。
2.rabbitmq消息队列的使用,要求保证服务随时可用,并保证消息队列内的消息不丢失。
rabibtmq在整个业务中的地位不比mysql低,高可用不可或缺。
rabbitmq集群
rabbitmq简单介绍:
基于erlang语言开发,而erlang是一门分布式语言开发,适用于集群开发;rabbitmq自身也提供了多种集群方案:http://www.rabbitmq.com/ha.html
1.集群管理:没有明显的主从,主要的是disk和ram节点的区别
2.做集群的需求:不支持跨网段(erlang限制)
3.集群类型:普通集群、镜像集群
普通集群:结构同步,消息实体只存在一个节点中,但consumer在非消息节点获取是,节点间存在消息拉取,易产生性能瓶颈。
镜像集群:集群中一个master,负责调度,处理消息实体,其他节点保存一份数据到本地;性能主要靠master承载。
4.持久化,分两部分:
Rabbitmq服务器配置持久化:默认的就是持久化(disc类型);
代码持久化:默认情况下,代码创建的消息队列和存放在队列里的消息都是非持久化的,需要在建立队列时指定:
import pika
username="guest"
password="guest"
user_pawd = pika.PlainCredentials(username,password)
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,credentials=user_pawd))
channel = connection.channel()
channel.queue_declare(queue='develop',durable=True) //持久化
channel.basic_publish(exchange='',routing_key='develop',body="Hello World",properties=pika.BasicProperties(delivery_mode=2,))
print "product a message to queue:queue1\tuse '# rabbitmqctl list_queues' to ckeck"
connection.close()
镜像集群搭建
1.时间同步,节点互通;节点hosts配置,能互相解析
10.11.45.1 node1 //用来做主节点
10.11.45.2 node2
2.节点cookie同步
/var/lib/rabbitmq/.erlang.cookie //文件内容可随意
3.保证节点rabbitqm-server都启动,默认都是主节点
# systemctl start rabbitmq-server.service
4.将节点node2加入到集群中(node1所在的集群),原节点中的队列会被清空。此时可以互相查看对方队列的信息,但未同步到本地。Exchange和binding会互相同步。
# rabbitmqctl stop_app
# rabbitmqctl join_cluster rabbit@node1
# rabbitmqctl start_app
# rabbitmqctl cluster_status //查看集群状态
5.设置镜像:作用是把master上面的队列同步到本地,在master宕机后一样可以维持队列。
# rabbitmqctl set_policy ha-1 "^ha\." '{"ha-mode":"all"}' //将ha开头的队列都镜像到所有节点上。
# rabbitmqctl set_policy ha-2 "^cinder" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}' //将cinder开头的队列镜像到任意两个节点,并自动同步
设置policy时的相关参数:
ha-mode:
exactly:指定数量的节点,需要配合ha-params(num类型)使用
nodes:指定特定镜像的节点,需要配合ha-params(string类型)使用
all:镜像到所有节点
也可以通过web管理界面设置:
集群问题,很难遇到
1.网络分区(脑裂),主要受erlang语言影响
判断依据:# rabbitmqctl cluster_status 结果中的partitions部分不为空
可用配置项:
ignore:默认,不处理网络分区,适用于网络状况好的集群
autoheal:各分区协商后重启客户端连接最少分区的节点,恢复集群
pause_minority:分区发生后判断自己所在分区内节点是否超过集群总节点数一半,如果没有超过则暂停这些节点(保证 CP,总节点数为奇数个)
keepalive高可用
1.安装:
# yum install keepalive ipsrv
2.配置:对外提供VIP 10.11.45.100
根据节点调整优先级大小,越大越优;节点间互相指定单播地址
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id mq_1
}
vrrp_script check_mq {
script "/etc/keepalived/check_mq.sh"
interval 20
weight -5
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 52
priority 94
advert_int 1
unicast_src_ip 10.11.45.1
unicast_peer {
10.11.45.2
}
authentication {
auth_type PASS
auth_pass 2222
}
virtual_ipaddress {
10.11.45.100
}
track_script {
check_mq
}
preempt_delay 10
}
3.检查脚本(/etc/keepalived/check_mq.sh):
#!/bin/bash
A=`rabbitmqctl status|wc -l`
if [ $A -lt 40 ];then
/bin/systemctl stop rabbitmq-server.service
/bin/systemctl stop keepalived.service
exit 1
fi
4.启动keepalived,查看VIP和日志
# systemctl start keepalived
# ip addr
# tailf /var/log/messages
集群中注意点:
1.开机不自启:keepalive和rabbitmq服务都设置成开机不自启动,手动启动减少风险。
2.服务启动顺序:rabbitmq集群同步后在启动keepalive。
故障处理
情形1:一个失效,一个存活(集群依旧可用,存活的保持为主)
1.业务低峰期启动失效的rabbitmq,自动同步队列,恢复队列集群。
2.配置并验证失效的keepalived优先级低于存活那台,不抢占VIP,保持VIP和rabbitmq主为同一台。
3.启动keepalived,高可用集群恢复。
情形2:两台均失效(集群失效,重大故障)
1.通过查日志、监控等记录找出后宕机的节点(比如是node2)。
2.启动后宕机节点(node2)的rabbitmq,确认消息是否丢失。
3.启动另一台rabbitmq(node1),恢复队列集群。
4.调整两台keepalived的优先级别:node2 > node1。
5.启动node2上面的keepalived,确认占用VIP。
6.启动node1上的keepalived,高可用集群恢复。