暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

RabbitMQ之注意事项

不修边幅的创客 2020-09-11
883

点击上方蓝色字体,选择“设为星标”



本篇文章总结了一些关于Rabbit MQ零碎的知识点,比如:元数据、从集群中剔除一个节点、日志、单点故障恢复和其它迁移方案等.

01 从RabbitMQ集群中剔除一个节点

1、假设一个前提


以 node1、 node2 和 node3 组成的集群为例,这里有两种方式将 node2 剥离出当前集群。


2、三个节点存活的情况下剔除node2

如果node2存活,可以通过reset命令剔除,则在node2这机器上执行以下命令即可:
#关闭node2的rabbitmq服务
rabbitmqctl stop_app
#重置当前节点
rabbitmqctl reset
#本步骤可有可无,起来后的节点是个单点了,node2已经被剔除
rabbitmqctl start_app
#通过查看状态查看是否已经被剔除
rabbitmqctl cluster_status


正如之前所说的,rabbitmqctl reset 命令将清空节点的状态,并将其恢复到空白状态。当重设的节点是集群中的一部分时,该命令也会和集群中的磁盘节点进行通信,告诉它们该节 点正在离开集群。不然集群会认为该节点出了故障,并期望其最终能够恢复过来。

3、node2已经挂了的情况下,如何剔除node2


此种情况下,可以在两外两个存活的节点上,执行如下命令,比如在node1上执行:

[root@node1 ~]# rabbitmqctl forget_cluster_node rabbit@node2
Removing node rabbit@node2 from cluster

注意:

      如果一个节点故障了,不要盲目的重启,盲目重启可能会引起脑裂(网络分区),先在好的节点上执行: rabbitmqctl forget_cluster_node rabbit@故障节点 , 删除故障节点的mnesia数据,在重启.


4、所有节点都故障了,剔除node2才能重启


下面的场景适合,所有节点都故障,首节点启动不了的问题:
还有一种情况,集群中节点按照 node3、node1、node2 的顺序关闭,此时如果要启动 集群,就要先启动 node2节点。如果最后一个关闭的节点node2最终由于某些异常而无法启动,这是必须剔除node2,集群才能启动,应该怎么做呢?
[root@node1 ~]# rabbitmqctl forget_cluster_node rabbit@node2 –offline
Removing node rabbit@node2 from cluster
* Impersonating node: rabbit@node1... done
* Mnesia directory : /opt/rabbitmq/var/lib/rabbitmq/mnesia/rabbit@node1
[root@node1 ~]# rabbitmq-server -detached
Warning: PID file not written; -detached was passed.
[root@node1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@node1
[{nodes,[{disc,[rabbit@node1,rabbit@node3]}]},
{running_nodes,[rabbit@node1]},
{cluster_name,<<"rabbit@node2">>},
{partitions,[]},
{alarms,[{rabbit@node1,[]}]}]

注意:

上面在使用 rabbitmqctl forget_cluster_node 命令的时候用到了 “--offline”参数,如果不添加这个参数,就需要保证 node2 节点中的 RabbitMQ 服务处于 运行状态,而在这种情况下,node2 无法先行启动,则“--offline”参数的添加让其可以在非运行状态下将 node1 剥离出当前集群。

02 RabbitMQ的日志


1、RabbitMQ的日志种类


RabbitMQ的日志有两种类型,如下图:

SASL(System Application Support Libraries,系统应用程序支持库)是库的集合,作为Erlang-OTP发行版的一部分,他们帮助开发者在开发Erlang应用程序时提供一系列标准,其中之一是日志记录格式.
所以当RabbitMQ记录Erlang相关信息时,它会将日志写入文件:RABBITMQ_NODE-sasl.log中. 举例来说,可以在这个文件中找到Erlang的崩溃报告,有助于调试无法启动的RabbitMQ节点.
 如果想查看RabbitMQ应用服务日志,则需要查阅RABBITMQ_NODENAME.log这个文件,所谓的RabbitMQ服务日志指的就是这个文件.


2、日志展示


如果使用rabbitmqctl stop_app命令关闭的RabbitMQ应用服务,那么在使用rabbitmqctl start_app命令开启RabbitMQ应用服务时的启动日志和rabbitmq-server的启动日志相同.

如果使用rabbitmqctl stop命令,会将Erlang虚拟机一同关闭,而rabbitmqctl stop_app只关闭RabbitMQ应用服务,在关闭的时候要多家注意他们的区别.

rbbitmqctl stop_app对应的服务日志:

rabbitmqctl stop来进行关闭,则会多出下面的日志,即关闭Erlang虚拟机.

3、程序自动采集日志

在RabbitMQ中,查看服务日志的方式不止有人工查看:RABBITMQ_NODE-sasl.log.下面介绍如何通过程序化的方式来查看相应的日志,RabbitMQ默认会创建一些交换器,其中 amq.rabbitmq.log就是用来收集RabbitMQ日志,集群中所有的服务日志都会往这个交换器中.这个交换器的类型为topic,可以收集如前面所说的debug、info、warning和error这4个级别的日志.

如图,我们创建4个日志队列:queue.debug、queue.info、queue.warning和queue.error,分别采用debug、info、warning和error这4个路由键来绑定amq.rabbitmq.log.如果要使用一个队列来收集所有级别的日志,可以使用“#”这个路由键:

    如果RabbitMQ集群中只有一个节点,那么这个4个日志队列可以收到此节点的所有日志.对于集群中有多个节点的情况同样适用,值得注意的是:对于每个级别的日志队列来说,比如queue.info,它会收到每个节点的info级别的日志,不过这些日志是交错的,不能区分是哪个具体节点的日志.代码如下:

03 RabbitMQ之单点故障



单点故障包括:机器硬件故障、机器掉电、网络异常、服务进程异常.
对于单点故障,此时需要在集群中的其他节点中执行 rabbitmqctl forget_cluster_node {nodename}命令来将故障节点剔除,其中nodename表示故障机器节点.
总之:对于故障节点不能盲目的重启,应该把故障节点的数据删除,重启,然后在加入到原来的集群

04 RabbitMQ之其它迁移方案总结



前面讲过一个方案:RabbitMQ之机房迁移,现在在讲一个方案:


a、步骤1

       在新机房创建与老机房等实例(包括内存和磁盘节点)RabbitMQ集群集群,创建方式,见:RabbitMQ之安装部署


b、步骤2

       

      1、迁移之前先停止在老集群中创建元数据(包括exchange、queue、vhost、user等);

2、通过老集群的RabbitMQ管理平台,导出元数据metadata.json, 在新集群中导入metadata.json,这样新集群就有了元数据;

注意:

这个地方会有问题,因为导入只能在一个节点导入,导入后元数据的主节点(master)都是这个节点,当前节点会有压力,(可以通过解析metadata.json的通过http api写入,这样就随机放到一个节点)

      3、这个地方可以改进:可以考虑程序读取json文件,调用HTTP API随机写入某个节点,如下图:



c、步骤3

     数据迁移的主要原理   是先从原集群中将数据消费出来,然后存入一个缓存区中,另一个线程读取缓存区中的消息再发布到新的集群中,如此完成了数据迁移的动作,我们称之为:RabbitMQ ForwardMaker


 1、可以自己去写脚本实现两个集群的数据同步;

  2、使用RabbitMQ的插件Shovel实现来给你个集群的数据同步,把在使用的队列在新老集群之间配置同步,shovel原理 : https://www.jianshu.com/p/280c2e2e1c53;


d、步骤4

切换负载均衡服务


注意:

     此种方式只是一种选择,如果一个集群有很多的exchanges和queues,这种方式要创建很多shovel显然不合适.

05 RabbitMQ的元数据


RabbitMQ在内部维护基础零件(Queue Exchange Binding Vhost)的元数据(metadata),在构成RabbitMQ集群之后还有集群的元数据. 
  • Queue metadata—Queue names and their properties (are they durable or auto-delete?)

  • Exchange metadata—The exchange’s name, the type of exchange it is, and what the properties are (durable and so on)

  • Binding metadata—A simple table showing how to route messages to queues

  • Vhost metadata—Namespacing and security attributes for the queues, exchanges,and bindings within a vhost 

  • Rabbit node location  

单节点的情况,RabbitMQ会在内存中维护一份元数据信息,并把标记为Durable的Queue和Exchange(以及相关bingding)持久化到磁盘.

引入了集群之后,会新增几种元数据信息:集群节点位置信息(Erlang节点名包含这部分信息),以及节点之间的关系信息.集群环境中你还会面临一个选择是存储元数据到RAM Only还是Disk 磁盘,在单节点情况由于没有额外的数据冗余存在所以这个选择默认是持久化到磁盘.


文章转载自不修边幅的创客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论