1. 查看RabbitMQ基本信息
rabbitmqctl status #单节点MQ状态
rabbitmqctl report #集群状态,包括各个节点MQ状态、镜像队列状态等
memory total是MQ进程实际占用内存大小,vm_memory_limit是限制MQ进程使用的内存大小。当memory total > vm_memory_limit * vm_memory_high_watermark_paging_ratio时,触发流控(flow control),生产速度下降;当memory total > vm_memory_limit时,触发阻塞(block),生产速度停止。
发生故障时,建议先查看RabbitMQ集群状态,保存日志,以便分析定位。
2. 查看RabbitMQ运行状态
由于RabbitMQ使用erlang -detached方式后台运行,在机器上可以通过remote shell直接连上erlang shell,查看运行状态。
erl -sname test -remsh rmq@rmq -setcookie XXXXXXXXXXX
使用etop分析erlang任务。
spawn(fun() -> etop:start([{output, text}, {interval, 5}, {lines, 10}, {sort, msg_q}]) end).
spawn(fun() -> etop:start([{output, text}, {interval, 5}, {lines, 10}, {sort, reductions}]) end).
使用process_info查看进程状态。
process_info(pid(0, 291, 0)).
正常情况下进程邮箱(MsgQ)是一个很小的值。当MsgQ值较大时,可能是进程阻塞(gen_server等),或者是收到了无法匹配的消息(selective receive),此时可以查看进程状态定位出错模块和消息类型。
3. 镜像队列状态与同步
rabbitmqctl stop命令并等待程序停止,异常退出包括进程crash、kill、机器宕机等。
镜像队列同步状态可以在web UI查看,也可以通过以下命令。
rabbitmqctl list_queues name slave_pids synchronised_slave_pids
当集群中存在已同步节点时,master退出不影响正常服务,集群将一个已同步slave节点提升为master。
当集群中没有已同步节点时,master正常退出,队列将不可服务(DOWN状态),待master重新启动后,服务恢复(确保了未同步数据的可靠性);master异常退出时,集群提升最老的slave为新master服务继续,原master未同步数据将丢失(原master异常退出后,数据处于未知状态,该处理确保了可用性)。
对于镜像队列,建议至少保持一个同步节点。
在集群没有已同步节点时,要重启master,需先同步数据。
rabbitmqctl sync_queue name
队列处于不可服务状态(DOWN),如果原master磁盘文件无法备份,只能删除并重建队列(数据完全丢失)。
rabbitmqctl forget_cluster_node old_master@old_master #自动删除old_master队列
rabbitmqctl forget_cluster_node old_master@old_master --offline #节点已退出时调用
若能够备份磁盘文件,则可以通过文件恢复原队列数据。
4. 数据恢复
备份RABBITMQ_MNESIA_DIR(/data/rabbitmq/mnesia/node_name)目录,复制到一个新节点上。修改新节点hostname(包括RABBITMQ_NODENAME、/etc/hosts等)、erlang cookie(/var/lib/rabbitmq/.erlang.cookie)保持与旧节点一致。
原节点不属于镜像队列,直接启动新节点即可。
原节点属于镜像队列,集群中无其他节点运行时,可以只启动新节点,恢复原节点数据。
rabbitmqctl force_boot #忽略集群master,直接启动当前节点
/etc/init.d/rabbitmq-server start #启动后仅能操作old_master队列,其他队列DOWN
原节点属于镜像队列,集群中有其他节点运行时,直接启动新节点,新节点加入集群,已中断服务的队列恢复正常(无数据丢失)。
5. 替换机器
集群添加节点时:先加入(join_cluster),后oss扩容。加入集群操作:
rabbitmqctl stop_app
rabbitmqctl join_cluster name@node
rabbitmqctl start_app
集群删除节点时:先oss缩容,后退出(reset)。退出集群操作:
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
原集群存在A、B两个节点,将B节点替换为C节点流程:
a.修改C节点hostname,haproxy配置;修改A、C节点/etc/hosts,保持一致
b.启动C节点haproxy和RabbitMQ,加入A节点集群(rabbitmqctl join_cluster A@A)
c.修改A节点haproxy配置,并重启haproxy
d.在OSS将C节点扩容到集群
e.待集群同步后,在OSS将B节点从集群中缩容
f.在B节点上,退出集群(rabbitmqctl reset)
g.修改A、C节点/etc/hosts,去掉B节点(可选)
修改hostname:
hostname "$NODE_NAME" #临时修改hostname,重启后失效
echo "$NODE_NAME" > /proc/sys/kernel/hostname #永久修改hostname,重启后仍有效
sed -i '/HOSTNAME/'d /etc/sysconfig/network
echo "HOSTNAME=$NODE_NAME" >> /etc/sysconfig/network
sed -i '/RABBITMQ_NODENAME/'d /etc/rabbitmq/rabbitmq-env.conf #rabbit nodename
echo "RABBITMQ_NODENAME=$NODE_NAME" >> /etc/rabbitmq/rabbitmq-env.conf
修改C节点/etc/hosts时,当A节点是master时,C节点/etc/hosts不用配置B;当A节点不是master时,C节点需要配置B。建议直接将B加入/etc/hosts.
6. 数据迁移
使用dynamic shovel将一个队列数据迁移到另一个队列。
rabbitmqctl set_parameter shovel my-shovel
'{"src-uri": "amqp://", "src-queue": "my-queue", \
"dest-uri": "amqp://remote-server", "dest-queue": "another-queue"}'