《RabbitMQ实战指南》整理(五)RabbitMQ运维

一、集群搭建

RabbitMQ集群允许消费者和生产者在RabbitMQ单个节点奔溃的情况下继续运行,它可以通过添加更多的节点来线性地扩展消息通信的吞吐量,当失去一个RabbitMQ节点时,客户端能够重新连接到集群中的任何其他节点并继续生产或消费。当集群中的一个RabbitMQ节点奔溃时,该节点上的所有队列上的消息也会丢失,RabbitMQ集群中的所有节点都会备份所有的元数据信息,包括:①队列的名称及属性;②交换器的名称及属性;③绑定关系数据;④vhost元数据。但是只有队列的所有者知道队列的所有信息,所以会有队列消息丢失的问题(可以通过如镜像队列解决)

1、多机多节点配置

多机多节点是指多台机器组成一个RabbitMQ集群。第一步需要配置各个节点的host文件,让节点之间能够识别对方的存在;第二步需要编辑RabbitMQ的cookie文件,确保各个节点的cookie文件使用的是同一个值,这里的cookie相当于密钥,各节点间通过密钥互相认证;第三步配置集群,可以通过rabbitmqctl工具配置,或者通过config文件配置,或者通过rabbitmq-autoCluster插件配置。

如果关闭了集群中的所有节点,需要确保在启动的时候最后关闭的节点是第一个启动的,否则这个不是最后关闭的节点会等待最后关闭的节点启动,等待时间是30秒,如果没有等到这个先启动的节点也会失败,默认会重试10次30秒,如果重试还是失败,当前节点会因失败关闭自身的应用。如果最后一个关闭的节点最终由于某些异常而无法启动,则可以通过rabbitmqctl forget_cluster_node命令来将此节点剔出当前集群。如果集群中的所有节点由于非正常因素如断电而关闭,那么集群中的所有节点都会认为还有其他节点在它后面,此时需要使用rabbitmqctl force_boot命令来启动一个节点,之后集群才能正常启动

2、集群节点类型

RabbitMQ中的每一个节点,要么是内存节点,要么是磁盘节点。内存节点是指将所有的队列、交换器、绑定关系、用户、权限和vhost的元数据定义都存储在内存中,而磁盘节点则将这些存储到磁盘中。单节点的集群中只有磁盘类型的节点,而在集群中可以配置部分节点为内存节点,以获得更高的权限。

如果集群已经搭建好了,那么可以使用rabbitmqctl change_cluster_node_type{disc,ram}命令来切换节点的类型,其中disc表示磁盘节点,而ram表示内存节点。

RabbitMQ要求在集群中至少有一个磁盘节点,其他节点可以是内存节点,当节点加入或离开集群时,它们必须将变更通知到至少一个磁盘节点,如果只有一个磁盘节点且其刚好崩溃了,那么集群可以继续发送或接受消息,但是不能执行创建队列、交换器、绑定关系、用户、以及更改权限、添加或删除集权节点的操作。当内存节点重新启动后,它们会连接到预先配置的磁盘节点,下载当前集群元数据的副本。为确保集群消息的可靠性,或者不确定使用哪个节点类型时,建议全部使用磁盘节点

3、剔除单个节点

有两种常用的方式可以将节点剔除出集群。第一种,在需要剔除的节点上执行rabbitmqctl stop_app或stop命令来关闭rabbitmq服务。之后在其他的节点上执行rabbitmqctl forget_cluster_node rabbit@xxx剔除节点,这种方式适合当前节点不再允许RabbitMQ的情况。第二种方式是在需剔除的节点上执行rabbitmqctl reset命令

4、集群节点的升级

如果RabbitMQ集群由单独的一个节点组成,只需关闭原来的服务,然后解压新的版本运行即可。如果RabbitMQ集群由多个节点组成,那么可以参考单个节点的情形:①使用rabbitmqctl stop命令关闭所有节点的服务;②保存各个节点的Mnesia数据;③解压新版本的RabbitMQ到指定的目录;④指定新版本的Mnesia路径为步骤二中的数据路径;⑤启动新版本的服务,注意需要启动原版本中最后关闭的节点

5、单机多节点配置

在一台机器上部署多个RabbitMQ服务节点,需要确保每个节点都有独立的名称、数据存储位置、端口号等。如果发生后续节点启动报错,大多数是由于配置问题,比如RabbitMQ Management插件配置了一样的端口号等。启动完各节点的服务之后,将节点添加到集群中就可以了。在实际应用时,建议搭建多机多节点集群,单机多节点可在实试验时应用。

二、查看服务日志

1、启动RabbitMQ服务

启动RabbitMQ服务可以使用rabbitmq-server-detached命令,这个命令会启动Erlang虚拟机和RabbitMQ应用服务,rabbitmqctl start_app用来启动RabbitMQ应用服务,而RabbitMQ应用服务启动的前提时Erlang虚拟机是正常运行的。

在RabbitMQ中,日志级别有none、error、warning、info、debug这5种,下一层级别的日志输出均包含上一层级别的日志输出,如warning级别的日志包含warning和error级别的日志。

2、关闭RabbitMQ服务

如果使用rabbitmqctl stop命令,会将Rrlang虚拟机一同关闭,而rabbitmqctl stop_app只会关闭RabbitMQ应用服务

3、其它

RabbitMQ种可以通过rabbitmqctl rotate_logs {suffix}命令来轮换日志,比如:rabbitmqctl rotate_logs .bak会在日志目录下建立新的日志文件,并将老的日志添加.bak的方式区分保存。此外也可以通过程序化的方式查看服务日志,设置相应的逻辑规则,将有用的日志信息过滤并保存起来一边后续的服务应用

三、单节点故障恢复

配置数据节点冗余可以有效防止由於单点故障而降低整个集群的可用性、可靠性。单点节点的故障主要包括:机器硬件故障、断电、网络异常、服务进程异常

  • 单点硬件故障包括机器硬盘、内存、主板等故障造成的死机,无法从软件层面恢复。此时需要在集群种的其它节点执行rabbitmqctl forget_cluster_nodes {nodename}命令来将故障节点剔除。如果之前有客户端连接到故障节点,需要将故障节点的IP地址从连接列表种删除,并让客户端重新连接以恢复整个应用
  • 如果遇到断电故障,需要接通电源后重启机器,此时节点上的RabbitMQ处于Stop状态,此时需要从其它节点执行rabbitmqctl forgrt_cluster_nodes {nodeName}将节点从集群种剔除,然后剔除当前故障RabbitMQ种的Mnesia数据,然后重启RabbitMQ服务,最后将其作为新节点加入到当前集群种,否则可能会引起网络分区
  • 网络故障极易引发网络分区,如发生网络肆但未发生网络分区,应第一时间关闭节点上的RabbitMQ进程,等待网络恢复后重启,如果已经发生了网络分区,可以参考后续章节手动进行操作
  • 服务异常时,如RabbitMQ未终止,需要判断风险是否可控,如不可控建议抛弃节点,一般情况下重新启动服务进程即可

四、集群迁移

RabbitMQ种的集群迁移更多是用来解决集群故障不可短时间内修复而将所有的数据、客户端等迁移到新的集群种,以确保服务的可用性。RabbitMQ集群迁移包括元数据重建、数据迁移以及与客户端连接切换

1、元数据重建

元数据重建是指在新的集群种创建原集群的队列、交换器、绑定关系、vhost、用户、权限和Prameter等数据信息,元数据重建后才可以将原集群种的消息及客户端连接迁移过来。

手动创建元数据是十分低效的,可以通过Web管理页面种的Download broker definitions按钮下载集群的元数据信息文件,之后再点击Upload broker definitions按钮上传元数据文件,如果新集群的数据与当前数据有冲突,对于交换器、队列及绑定关系这类非可变对象会报错,对于其它可变对象如Parameter、用户等会被覆盖,如果导入过程种失败会只有部分数据加载成功

通过上述方法解决后会出现所有队列落在当前节点的情况,一般有两种方式解决,第一种是通过HTTP API接口在新集群上创建相应的数据,另外一种是随机连接集群种不同节点的IP再创建队列等信息。

2、数据迁移和客户端连接的切换

一种方式是等待原集群中的所有消息全部消费完成后再将连接断开,再建立新的连接进行消费。但如果出现因服务故障无法等到的情况,则需要将原集群中的数据消费出来,存入一个缓存区中,另一个线程读取缓存区中的消息再发布到新的集群中。RabbitMQ提供的Federation和Shovel插件即可实现类似的功能

3、自动化迁移

要实现集群自动化迁移,需要在使用相关资源时就做好准备,与生产者消费者客户端相关的是交换器、队列及集群的信息,当这3类资源发生改变时需要让客户端迅速感知,以便进行相应的处理。可以将相应的资源加载到Zookeeper的相应节点中,客户在客户端为对应的资源节点加入watcher来感知变化。

五、集群监控

1、通过HTTP API接口提供监控数据

RabbitMQ Management插件不仅提供了优秀的Web管理界面,还提供了HTTP API接口以供调用。集群节点的信息可以通过/api/nodes接口来获取;对于交换器而言的数据采集可以调用/api/exchange/vhost/name接口(操作默认主机时需要将“/”转义成%2F否则会异常);队列的数据采集接口为/api/queues/vhost/name

2、通过客户端提供监控数据

.NET中的RabbitMQ.Client的IModel也提供了ConsumerCount(string queue)和MessageCount(string queue)方法,可以分别获取队列中消费者的个数和查询队列中的消息个数

3、检查RabbitMQ服务是否健康

为判断RabbitMQ是否具备服务外部请求的能力,可以使用AMQP协议来构建一个类似于TCP协议中的Ping检测程序,当无法建立TCP协议层面的连接,获取无法构建AMQP协议层面的连接,或者构建连接超时时,可以判定RabbitMQ服务处于异常状态而无法正常为外部应用提供相应的服务。

除了基于上述的行为构建程序外还可以使用RabbitMQ Management插件提供的/api/aliveness-test/vhost的HTTP API接口,通过:①创建aliveness-test名称的队列来接受测试消息;②使用该队列名称作为消息的路由键,将消息发往默认交换器;③到达队列时就消费消息,否则报错的方式来验证RabbitMQ服务的健康性,它不会收到网络问题的影响,且不会删除创建的队列,还能避免元数据事务对Mnesia数据库造成的压力

此外还可以使用/api/healthchecks/node和/api/healthchecks/node/node这两个接口对当前节点或指定节点进行健康检查,包括RabbitMQ应用、信道、队列是否正常运行,是否有告警产生等

4、元数据管理与监控

管控的介入会降低消息中间件的灵活度,但是可以增强系统的可靠性,比如可以建立元数据审查系统来配置对应的元数据资源。这里提供一种思路:所有的业务应用都需要通过元数据审查系统来申请创建相应的元数据信息,申请后进行审批,之后再在数据库中存储和在RabbitMQ集群中相应的元数据,在数据库和RabbitMQ集群之间可以添加一个一致性校验程序来检测元数据不一致的记录信息,上传至监控管理系统,最后进行人工介入处理。元数据一致性检测程序可以通过/api/definitions的HTTP API接口来获取集群的元数据信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章