- 优化RabbitMQ集群
- 什么是真正的高可用
- 网络分区故障
- RabbitMQ状态监控
- 使用DockerCompose部署高可用集群
- 什么是Docker Compose
- 安装 Docker Compose
- 将4个 RabbitMQ 节点搭建为集群
- 使用Kubernetes部署高可用集群
- 什么是Kubernetes
- Kubernetes相关概念:
- Kubernetes搭建RabbitMQ集群的脚本
- 网络分区故障
- 什么是网络分区
- RabbitMQ集群网络模型
- RabbitMQ集群网络分区的意义
- 集群网络分区处理方法
- ◆ 手动处理
- ◆ 自动处理
- 总结
- RabbitMQ状态监控方式
- 目前的项目不足之处分析
◆ 在传统以物理机/虚拟机为基础的架构中,服务宕机往往需要人工处理
◆ 随着容器技术的发展,容器编排框架可以很好的解决高可用问题
◆ K8S已经成为容器编排的事实标准,能够承载RabbitMQ集群
◆ 在实际生产中,网络分区是非常常见的故障原因
◆ 网络分区的排查和处理难度较大,需要专门门研究
◆ 在生产环境中,需要实时关注RabbitMQ集群状态
◆ RabbitMQ状态包括流量、内存占用、CPU占用等
docker 启动 rabbitmq:
docker run -di --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
◆ Compose是用于定义和运行多容器Docker应用程序的工具
◆ 通过Compose,可以使用YAML文件来配置应用程序需要的所有服务
◆ 使用一个命令,就可以从YAML文件配置中创建并启动所有服务
- 安装python3-pip
dnf install python3-pip - 安装docker-compose
pip3 install docker-compose - 查看版本
docker-compose version
(由于链接资源是外网,如果安装不成功,提示docker-compose 命令不存在,可线下进行安装)
cd /apps/rabbitmq/ wget https://github.com/docker/compose/releases/download/1.14.0-rc2/docker-compose-Linux-x86_64 rename docker-compose-Linux-x86_64 docker-compose docker-compose-Linux-x86_64 mv docker-compose /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
- 使用 Docker Compose 启动3个 RabbitMQ 节点
cd /apps/rabbitmq/
vim docker-compose.yml
version: "2.0" services: master: image: rabbitmq:3-management hostname: master ports: - 5672:5672 #集群内部访问的端口 - 15672:15672 #外部访问的端口 environment: - RABBITMQ_DEFAULT_USER=guest #用户名 - RABBITMQ_DEFAULT_PASS=guest #密码 - RABBITMQ_ERLANG_COOKIE='ktrabbitmq' salve1: image: rabbitmq:3-management hostname: salve1 ports: - 5673:5672 #集群内部访问的端口 environment: - RABBITMQ_ERLANG_COOKIE='ktrabbitmq' links: - master salve2: image: rabbitmq:3-management hostname: salve2 ports: - 5674:5672 #集群内部访问的端口 environment: - RABBITMQ_ERLANG_COOKIE='ktrabbitmq' links: - master - salve1 salve3: image: rabbitmq:3-management hostname: salve3 ports: - 5675:5672 #集群内部访问的端口 environment: - RABBITMQ_ERLANG_COOKIE='ktrabbitmq' links: - master - salve1 - salve2将4个 RabbitMQ 节点搭建为集群
-
启动docker-compose,按照脚本启动集群
docker-compose up -d -
启动集群后可以看看docker进程是是否启动成功
docker ps -
进入master节点,启用管控台插件,启动后可在web打开rabbitMQ管控台
docker exec -it rabbitmq_master_1 bash
rabbitmq-plugins enable rabbitmq_management
默认用户名: guest 默认密码: guest -
所有salve关联加入集群
进入salve1节点
docker exec -it rabbitmq_salve1_1 bash
停止salve1节点的rabbitmq
rabbitmqctl stop_app
配置salve1节点,加入集群
rabbitmqctl join_cluster rabbit@master
启动salve1节点的rabbitmq
rabbitmqctl start_app
进入salve2节点
docker exec -it rabbitmq_salve2_1 bash
停止salve2节点的rabbitmq
rabbitmqctl stop_app
配置salve2节点,加入集群
rabbitmqctl join_cluster rabbit@master
启动salve2节点的rabbitmq
rabbitmqctl start_app
进入salve3节点
docker exec -it rabbitmq_salve3_1 bash
停止salve3节点的rabbitmq
rabbitmqctl stop_app
配置salve3节点,加入集群
rabbitmqctl join_cluster rabbit@master
启动salve3节点的rabbitmq
rabbitmqctl start_app
- 设置镜像模式
进入master内部,执行设置镜像模式即可:
docker exec -it rabbitmq_master_1 bash
rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:“all”}’
打开管控台:http://192.168.166.134:15672
可看到集群已经搭好,并且所有结点已为镜像模式
◆ Kubernetes可以自动化调度、运维Docker容器
◆ Kubernetes已经成为微服务基础架构的“事实标准”
◆ Pod: K8S中的最小业务单元,内含一个或多个容器
◆ StatefulSet: 定义一组有状态Pod,K8S将自动维护
◆ Deployment: 定义一组无状态Pod, K8S将 自动维护
◆ Service: 一组Pod的抽象访问方式,相当于负载均衡器
kind: Service # 相当于负载均衡层 apiVersion: v1 metadata: # 元数据 namespace: test-rabbitmq name: rabbitmq labels: app: rabbitmq type: LoadBalancer spec: type: NodePort ports: - name: http protocol: TCP port: 15672 targetPort: 15672 nodePort: 31672 - name: amqp protocol: TCP port: 5672 targetPort: 5672 nodePort: 30672 selector: app: rabbitmq --- apiVersion: v1 # 用于注入配置文件 kind: ConfigMap metadata: name: rabbitmq-config namespace: test-rabbitmq data: enabled_plugins: | [rabbitmq_management,rabbitmq_peer_discovery_k8s]. rabbitmq.conf: | cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s cluster_formation.k8s.host = kubernetes.default.svc.cluster.local cluster_formation.k8s.address_type = ip cluster_formation.node_cleanup.interval = 30 cluster_formation.node_cleanup.only_log_warning = true cluster_partition_handling = autoheal loopback_users.guest = false --- apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: rabbitmq namespace: test-rabbitmq spec: serviceName: rabbitmq replicas: 4 template: metadata: labels: app: rabbitmq spec: serviceAccountName: rabbitmq terminationGracePeriodSeconds: 10 containers: - name: rabbitmq image: rabbitmq:3-management volumeMounts: - name: config-volume mountPath: /etc/rabbitmq ports: - name: http protocol: TCP containerPort: 15672 - name: amqp protocol: TCP containerPort: 5672 livenessProbe: exec: command: ["rabbitmqctl", "status"] initialDelaySeconds: 60 periodSeconds: 60 timeoutSeconds: 10 readinessProbe: exec: command: ["rabbitmqctl", "status"] initialDelaySeconds: 20 periodSeconds: 60 timeoutSeconds: 10 imagePullPolicy: Always env: - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: RABBITMQ_USE_LONGNAME value: "true" - name: RABBITMQ_NODENAME value: "rabbit@$(MY_POD_IP)" - name: K8S_SERVICE_NAME value: "rabbitmq" - name: RABBITMQ_ERLANG_COOKIE value: "ktrabbit" volumes: - name: config-volume configMap: name: rabbitmq-config items: - key: rabbitmq.conf path: rabbitmq.conf - key: enabled_plugins path: enabled_plugins
由于目前没有Kubernetes的宿主机环境,只能记好笔记,以后再尝试。
网络分区故障 什么是网络分区网络分区指的是集群分裂为了两个网络“孤岛
◆ RabbitMQ集群采用单向环状网络模型
◆ 当网络部分异常时,环状网络异常,相关业务堵塞
◆ 此时可以人为造成网络分区,保存部分集群正常运行
步骤1:挂起客户端进程
可以减少不必要的消息丢失,如果进程数过多,可跳过
步骤2: 删除镜像队列的配置
如果没有删除镜像队列配置,恢复过程中可能会出现队列漂移
相关命令查看这:https://www.wangt.cc/2020/12/rabbitmq常用命令/
步骤3:挑选信任分区.
挑选的指标有:是否有disk节点 > 分区节点数 > 分区队列数 > 分区客户端连接数
步骤4:关闭非信任区的节点
采用rabbitmqctl stop_ app命令,只关闭RabbitMQ应用,不会关闭ErLang虚拟机.
步骤5:启动非信任区的节点
采用rabbitmqctl start_ app命令,启动过程中伴随着网络的修复
步骤6:检查网络分区是否恢复
- 若已经恢复跳转至步骤8
- 若还存在网络分区进行步骤7
步骤7:重启信任分区中的节点
使用步骤4与5的命令
步骤8:添加镜像队列的配置
rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:“all”}’
步骤9:恢复生产者和消费者的进程
若步骤1并未挂起客户端进程,也应该检查客户端连接,必要时重启客户端
RabbitMQ中有3种网络分区自动处理模式:
pause-minority/pause-if-all-down/autoheal
pause-minority:
◆ 发生网络分区时,节点自动检测自己是否处于少数派,若是则关闭自己
◆ 若出现了节点数相同的两个分区,可能会导致两个分区全部关闭
pause-if-all-down:
◆ 每个节点预先配置一个节点列表,当失去和列表中所有节点的通信时,关闭自己.
◆ 此方法考验配置的合理性,配置不合理可能会导致集群节点全部宕机
autoheal:
◆ 发生网络分区时,每个节点使用特定算法自动决定一个“获胜分区",然后重启不在分区的其他节点
◆ 当节点中有关闭状态时,autoheal不会起作用
默认是ignore模式:发生网络分区时,不做任何动作,需要人工介入。
如要开启,配置rabbitmq.config中的cluster_ parititon_ handling参数
◆ 集群网络分区有两种处理方式:手动和自动
◆ 手动处理方 式比较考验运维操作水平,但比较常用
◆ 慎用自动处理方式,因为如果配置不合理,会导致更大的问题
◆ 通过Java API判断节点是否健康
使用Java应用创建connection与channel
Connection connection = connect ionFac tory. newConnection() ;
Channel channel = connect ion. createChannel() ;
若能创建成功,则节点健康,若创建失败(抛异常)则节点
挂机或与节点的网络连接异常
◆ 通过HTTP Rest API监控集群状态(15672端口)
使用api/nodes/接口获得节点信息
使用api/exchanges/{vhost}/{name}/接口获得exchange状态信息
使用api/queues/{vhost}/{name}/接口获得queue状态信息
◆ 通过监控中间件监控RabbitMQ
常见的监控中间件有Zabbix、Prometheus等
Zabbix、Prometheus的底层原理 是调用HTTP Rest API,再讲数据处理、存储、展示
-
发送消息时无法自动重试
◆ 消息若发送失败,没有重试处理机制
◆ 若RabbitMQ集群短暂宕机,消息丢失,业务异常 -
无法得知接收方处理情况
◆ 发送方无法得知消息是否被处理
◆ 若消息丢失,业务异常 -
无法自动处理并标记死信
◆ 死信消息依赖人工处理,需要自动处理并标记
◆ 消息状态的标记依赖数据库或缓存,对消息状态进行存储
这些不足会在下一篇博文解决
RabbitMQ学习笔记(七)——RabbitMQ分布式事务框架



