前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RabbitMQ学习笔记(六)——优化RabbitMQ集群

RabbitMQ学习笔记(六)——优化RabbitMQ集群

作者头像
不愿意做鱼的小鲸鱼
发布2022-09-26 19:07:15
6170
发布2022-09-26 19:07:15
举报
文章被收录于专栏:web全栈web全栈

优化RabbitMQ集群

什么是真正的高可用

◆ 在传统以物理机/虚拟机为基础的架构中,服务宕机往往需要人工处理

◆ 随着容器技术的发展,容器编排框架可以很好的解决高可用问题

◆ K8S已经成为容器编排的事实标准,能够承载RabbitMQ集群

网络分区故障

◆ 在实际生产中,网络分区是非常常见的故障原因

◆ 网络分区的排查和处理难度较大,需要专门门研究

RabbitMQ状态监控

◆ 在生产环境中,需要实时关注RabbitMQ集群状态

◆ RabbitMQ状态包括流量、内存占用、CPU占用等

使用DockerCompose部署高可用集群

docker 启动 rabbitmq:

docker run -di --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management

什么是Docker Compose

◆ Compose是用于定义和运行多容器Docker应用程序的工具

◆ 通过Compose,可以使用YAML文件来配置应用程序需要的所有服务

◆ 使用一个命令,就可以从YAML文件配置中创建并启动所有服务

安装 Docker Compose

  1. 安装python3-pip dnf install python3-pip
  2. 安装docker-compose pip3 install docker-compose
  3. 查看版本 docker-compose version

(由于链接资源是外网,如果安装不成功,提示docker-compose 命令不存在,可线下进行安装)

代码语言:javascript
复制
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
  1. 使用 Docker Compose 启动3个 RabbitMQ 节点 cd /apps/rabbitmq/ vim docker-compose.yml
代码语言:javascript
复制
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 节点搭建为集群

  1. 启动docker-compose,按照脚本启动集群 docker-compose up -d
  2. 启动集群后可以看看docker进程是是否启动成功 docker ps
  3. 进入master节点,启用管控台插件,启动后可在web打开rabbitMQ管控台 docker exec -it rabbitmq_master_1 bash rabbitmq-plugins enable rabbitmq_management 默认用户名: guest 默认密码: guest
  4. 所有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

  1. 设置镜像模式 进入master内部,执行设置镜像模式即可: docker exec -it rabbitmq_master_1 bash rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

打开管控台:http://192.168.166.134:15672

可看到集群已经搭好,并且所有结点已为镜像模式

使用Kubernetes部署高可用集群

什么是Kubernetes

◆ Kubernetes可以自动化调度、运维Docker容器

◆ Kubernetes已经成为微服务基础架构的“事实标准”

Kubernetes相关概念:

◆ Pod: K8S中的最小业务单元,内含一个或多个容器

◆ StatefulSet: 定义一组有状态Pod,K8S将自动维护

◆ Deployment: 定义一组无状态Pod, K8S将 自动维护

◆ Service: 一组Pod的抽象访问方式,相当于负载均衡器

Kubernetes搭建RabbitMQ集群的脚本

代码语言:javascript
复制
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集群网络模型

◆ RabbitMQ集群采用单向环状网络模型

◆ 当网络部分异常时,环状网络异常,相关业务堵塞

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参数

总结

◆ 集群网络分区有两种处理方式:手动和自动

◆ 手动处理方 式比较考验运维操作水平,但比较常用

◆ 慎用自动处理方式,因为如果配置不合理,会导致更大的问题

RabbitMQ状态监控方式

◆ 通过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,再讲数据处理、存储、展示

目前的项目不足之处分析

  1. 发送消息时无法自动重试 ◆ 消息若发送失败,没有重试处理机制 ◆ 若RabbitMQ集群短暂宕机,消息丢失,业务异常
  2. 无法得知接收方处理情况 ◆ 发送方无法得知消息是否被处理 ◆ 若消息丢失,业务异常
  3. 无法自动处理并标记死信 ◆ 死信消息依赖人工处理,需要自动处理并标记 ◆ 消息状态的标记依赖数据库或缓存,对消息状态进行存储

这些不足会在下一篇博文解决

RabbitMQ学习笔记(七)——RabbitMQ分布式事务框架

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 优化RabbitMQ集群
    • 什么是真正的高可用
      • 网络分区故障
        • RabbitMQ状态监控
        • 使用DockerCompose部署高可用集群
          • 什么是Docker Compose
            • 安装 Docker Compose
              • 将4个 RabbitMQ 节点搭建为集群
              • 使用Kubernetes部署高可用集群
                • 什么是Kubernetes
                  • Kubernetes相关概念:
                    • Kubernetes搭建RabbitMQ集群的脚本
                    • 网络分区故障
                      • 什么是网络分区
                        • RabbitMQ集群网络模型
                          • RabbitMQ集群网络分区的意义
                            • 集群网络分区处理方法
                              • ◆ 手动处理
                              • ◆ 自动处理
                            • 总结
                            • RabbitMQ状态监控方式
                            • 目前的项目不足之处分析
                            相关产品与服务
                            容器服务
                            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档