需求背景

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管理界面设置:
rabbitmq高可用的实现_第1张图片

集群问题,很难遇到

1.网络分区(脑裂),主要受erlang语言影响
  判断依据:# rabbitmqctl cluster_status 结果中的partitions部分不为空
rabbitmq高可用的实现
  可用配置项:
    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,高可用集群恢复。