RabbitMQ原理架构解析:消息传递的核心机制

news2025/3/9 9:34:44

文章目录

  • 一、RabbitMQ简介
    • 1.1、概述
    • 1.2、特性
  • 二、RabbitMQ原理架构
  • 三、RabbitMQ应用场景
    • 3.1、简单模式
    • 3.2、工作模式
    • 3.3、发布订阅
    • 3.4、路由模式
    • 3.5 主题订阅模式
  • 四、同类中间件对比
  • 五、RabbitMQ部署
    • 5.1、单机部署
    • 5.2、集群部署(镜像模式)
    • 5.3、K8s部署
  • 六、常用命令
  • 七、RabbitMQ配置详解
  • 八、RabbitMQ优化
    • 8.1、加大服务器带宽
    • 8.2、加大内存
    • 8.3、使用固态硬盘
    • 8.4、增加生产者
    • 8.5、增加消费者
    • 8.6、改网络访问为本地访问
    • 8.7、消费端使用长连接
    • 8.8、消息不要超过4M
  • 九、监控
  • 十、常见故障与排查
    • 10.1、消费慢
    • 10.2、消息丢失
    • 10.3、消息重复消费
    • 10.4、报错“error in config file “/etc/rabbitmq/rabbitmq.config” (none): no ending found”
    • 10.5、生产者发送消息报错
    • 10.6、浏览器打开IP地址,无法访问 RabbitMQ(白屏没有结果)

一、RabbitMQ简介

1.1、概述

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而群集和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。

1.2、特性

可伸缩性:集群服务
消息持久化:从内存持久化消息到硬盘,再从硬盘加载到内存

解决什么问题:

  1. 进程间的通讯。程序间解耦(耦合)。
  2. web高并发。来不及进行同步处理。”too many connections”(同步 异步切换)

二、RabbitMQ原理架构

在这里插入图片描述
在这里插入图片描述
中间的Broker表示RabbitMQ服务,每个Broker里面至少有一个Virtual host虚拟主机,每个虚拟主机中有自己的Exchange交换机、Queue队列以及Exchange交换机与Queue队列之间的绑定关系Binding。producer(生产者)和consumer(消费者)通过与Broker建立Connection来保持连接,然后在Connection的基础上建立若干Channel信道,用来发送与接收消息
名词解释:

  1. exchange:它指定消息按什么规则,路由到哪个列队 给消息分类
  2. queue:消息载体,每个消息都会被投递到一个或多个列队里面。
  3. binding:exchange和queue按照规则绑定
  4. connections:producer和consumer用TCPconnections链接到rabbitMQ
  5. channels:TCP中的虚拟链接。(不损耗端口号)
  6. Routing key 路由关键字(消息路由)
  7. Send Message 发送消息
  8. Receive Message 收消息
  9. Broker 缓存代理

三、RabbitMQ应用场景

3.1、简单模式

做最简单的事情,一个生产者对应一个消费者,RabbitMQ相当于一个消息代理,负责将A的消息转发给B
应用场景:将发送的电子邮件放到消息队列,然后邮件服务在队列中获取邮件并发送给收件人、聊天等

3.2、工作模式

  1. 一条消息只会被一个消费者接收;
  2. rabbit采用轮询的方式将消息是平均发送给消费者的;
  3. 消费者在处理完某条消息后,才会收到下一条消息。
    应用场景:对于 任务过重或任务较多情况使用工作队列可以提高任务处理的速度。

3.3、发布订阅

  1. 每个消费者监听自己的队列。
  2. 生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息
    应用场景:用户通知,当用户充值成功或转账完成系统通知用户,通知方式有短信等多种方法 。比如邮件群发,群聊天,广告等。

3.4、路由模式

  1. 每个消费者监听自己的队列,并且设置routingkey。
  2. 生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。
    应用场景:如在商品库存中增加了1台iphone13,iphone13促销活动消费者指定routing key为iphone13,只有此促销活动会接收到消息,其它促销活动不关心也不会消费此routing key的消息

3.5 主题订阅模式

根据主题(Topics)来接收消息,将路由key和某模式进行匹配,此时队列需要绑定在一个模式上,#匹配一个词或多个词,*只匹配一个词。
应用场景:同上,iphone促销活动可以接收主题为iphone的消息,如iphone12、iphone13等

四、同类中间件对比

特性ActiveMQRabbitMQRockerMQKafka
producer-comsumer(生产消费)支持支持支持支持
pubkish-subscribe(发布订阅)支持支持支持支持
request-reply(请求应答)支持支持
API完整性
多语言支持支持,
JAVA优先
无关JAVA支持,
JAVA优先
单机吞吐量万级万级万级十万级
消息延时毫秒微妙毫秒毫秒
可用性高(主从)高(主从)高(分布式)高(分布式)
消息丢失理论上
不会丢失
理论上
不会丢失
消息重复可控制理论上
会有重复
文档完整性
提供快速入门
社区活跃度
商业支持阿里云
成熟度成熟成熟比较成熟成熟日志领域
特点功能齐全,被大量开源项目使用由于Erlang语言开发,性能好各环节分布式设计,多种消费模式可靠性、可扩展、持久性、性能高
协议OPENWITE、STOP、REST、XMPP、AMQPAMQP自定义(社区提供JMS)PLAINTEXT、SSL、SASL_PLAINTEXT、SASL_SSL
持久化内存、文件、
数据库
内存、文件磁盘文件磁盘、文件
事务支持支持支持支持
负载均衡支持支持支持支持
管理界面一般有web console实现
优点成熟的产品,已经在很多项目得到应用。有较多文档,各种协议支持较好,多重语言的成熟客户端由于Erlang语言开发,mq性能好,管理页面丰富,多种语言支持,amqp客户端可用模型简单,接口易用,阿里大规模应用性能好,支持多种消费,开发都较活跃性能卓越、可用性非常高、日志领域比较成熟、功能简单、web界面友好
缺点会莫名丢失消息,目前社区对重心版本不是太活跃,5.x维护较少,不适合大规模队列由于Erlang语言开发,难度较大,不支持动态扩容产品文档匮乏,没有在mq核心去实现JMS等接口,对已有系统不能完美兼容消息失败不支持重试、消息顺序可能会导致消息乱序、社区更新较慢

五、RabbitMQ部署

5.1、单机部署

5.1.1安装erlang

yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel ncurses-devel  
wget https://github.com/erlang/otp/releases/download/OTP-24.0/otp_src_24.0.tar.gz 
tar -xzvf /otp_src_24.0.tar.gz 
cd /otp_src_24.0 
./configure --prefix=/usr/local/erlang --with-ssl --enable-threads --enable-smp-support --enable-kernel-poll --enable-hipe  
make && make install

5.1.2安装rabbitmq

wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.10.5/rabbitmq-server-3.10.5-1.el8.noarch.rpm 
rpm -ivh --nodeps rabbitmq-server-3.10.5-1.el8.noarch.rpm 
添加开机启动RabbitMQ服务 
chkconfig rabbitmq-server on 
启动RabbitMQ服务 
rabbitmq-server start 
后台启动RabbitMQ服务 
rabbitmq-server -detached 
停止RabbitMQ服务 
rabbitmqctl stop 
查看RabbitMQ服务状态 
rabbitmqctl status 
添加帐号:name 密码:
passwd rabbitmqctl add_user name passwd 
赋予其administrator角色 
rabbitmqctl set_user_tags name administrator 
删除角色 
rabbitmqctl delete_user Username 
设置权限
rabbitmqctl set_permissions -p / name ".*" ".*" ".*" 
查看用户的权限 
rabbitmqctl list_user_permissions username 

启动成功后,rabbitMQ的相关文件所在位置

  1. 相关命令 :/usr/lib/rabbitmq/bin/
  2. 相关的日志:/var/log/rabbitmq/
  3. 相关的配置 : /etc/rabbitmq/
  4. 设置的用户权限等元数据信息:/var/lib/rabbitmq/mnesia/
    http://ip:15672/尝试访问rabbitmq的web页面

可能会遇到报错情况,Node的错误,大概的意思就是说,hosts中的地址和node中的地址不一样,不匹配导致的。修改hosts文件中的本机的IP地址,hosts中的本机的计算机名称和Node的节点的名称保持一致即可。
在这里插入图片描述

5.2、集群部署(镜像模式)

普通模式:普通集群模式,就是将 RabbitMQ 部署到多台服务器上,每个服务器启动一个 RabbitMQ 实例,多个实例之间进行消息通信。
此时我们创建的队列 Queue,它的元数据(主要就是 Queue 的一些配置信息)会在所有的 RabbitMQ 实例中进行同步,但是队列中的消息只会存在于一个 RabbitMQ 实例上,而不会同步到其他队列。
当我们消费消息的时候,如果连接到了另外一个实例,那么那个实例会通过元数据定位到 Queue 所在的位置,然后访问 Queue 所在的实例,拉取数据过来发送给消费者。
这种集群可以提高 RabbitMQ 的消息吞吐能力,但是无法保证高可用,因为一旦一个 RabbitMQ 实例挂了,消息就没法访问了,如果消息队列做了持久化,那么等 RabbitMQ 实例恢复后,就可以继续访问了;如果消息队列没做持久化,那么消息就丢了。
在这里插入图片描述
镜像模式:它和普通集群最大的区别在于 Queue 数据和原数据不再是单独存储在一台机器上,而是同时存储在多台机器上。也就是说每个 RabbitMQ 实例都有一份镜像数据(副本数据)。每次写入消息的时候都会自动把数据同步到多台实例上去,这样一旦其中一台机器发生故障,其他机器还有一份副本数据可以继续提供服务,也就实现了高可用。
在这里插入图片描述
5.2.1 配置节点
1、配置两台机器的hosts
vim /etc/hosts修改后使用
2、停止服务

rabbitmqctl stop

3、设置erlang cookie
这里将第一台的该文件复制到 其他节点,由于这个文件权限是400,为方便传输,先修改权限,所以需要先修改该文件权限为 777。
集群各节点的cookie必须保持一致,否则无法通信。
erlang是通过主机名来连接服务,必须保证各个主机名之间可以ping通。可以通过编辑/etc/hosts来手工添加主机名和IP对应关系。如果主机名ping不通,rabbitmq服务启动会失败。
注意.erlang.cookie的目录,也有可能在/var/lib/rabbitmq/.erlang.cookie
将权限和所属用户/组修改回来
node2:

chmod 400 /root/.erlang.cookie

4、启动个节点

rabbitmq-server –detached

查看集群状态

[root@test-1]# rabbitmqctl cluster_status 
Cluster status of node rabbit@mq1 ... 
Basics 
Cluster name: rabbit@mq1.example.local    #集群名称 
Disk Nodes    #磁盘节点 
rabbit@mq1 
Running Nodes    #运作中节点
rabbit@mq1 
Versions    #版本 
rabbit@mq1: 
RabbitMQ 3.9.0 on Erlang 24.0.4 

5.2.2创建集群

rabbitmqctl stop_app    #停止 app 服务 
rabbitmqctl reset    #清空元数据 
rabbitmqctl join_cluster rabbit@mq1 --ram    #将rabbitmq-server2添加到集群当中,并成为内存节点,不加--ram默认是磁盘节点 
rabbitmqctl start_app    #启动 app 服务 
rabbitmqctl stop_app    #停止 app 服务 
rabbitmqctl reset    #清空元数据
rabbitmqctl join_cluster rabbit@mq1 --ram    #
将rabbitmq-server2添加到集群当中,并成为内存节点,不加--ram默认是磁盘节点 
rabbitmqctl start_app    #启动 app 服务  
​
将集群设置为镜像模式(只要在其中一台节点执行以下命令即可) rabbitmqctl set_policy ha-all "#" '{"ha-mode":"all"}'
http://ip:15672/尝试访问rabbitmq的web页面

在这里插入图片描述

5.3、K8s部署

5.3.1 创建yaml文件
包括(comfigmap、secret、rbac、sts、svc)五个yaml文件
Comfigmap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: rabbitmq-config
  namespace: test
data:
  enabled_plugins: |
      [rabbitmq_management,rabbitmq_peer_discovery_k8s].
#启用插件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 = hostname
      #################################################
      # rabbit-mq is rabbitmq-cluster's namespace#
      #################################################
      cluster_formation.k8s.hostname_suffix = .rabbitmq-headless.rabbit-mq.svc.cluster.local
      cluster_formation.node_cleanup.interval = 30
      cluster_formation.node_cleanup.only_log_warning = true
      cluster_partition_handling = autoheal
      queue_master_locator=min-masters
      cluster_formation.randomized_startup_delay_range.max = 2
      vm_memory_high_watermark.absolute = 1GB
      disk_free_limit.absolute = 2GB
      loopback_users.guest = false

Secret.yaml:
用来存储rabbitmq的用户名、密码及erlang.cookie。
erlang创建步骤:erlang是集群之间互访的秘钥
首先需要生成一个erlang.cookie的文件: echo $(openssl rand -base64 32) > erlang.cookie
然后再生成base64的值 如:echo -n ‘v/sWCz4uKETUvneRyJVn87Jg15si2eGaWg54Yvefhrk=’ |base64

 apiVersion: v1
kind: Secret
metadata:
  name: devsecret
  namespace: test
type: Opaque
data:
  rabbitDefaulUser: "YWRtaW4="  # echo -n 'admin' |base64
  rabbitDefaultPass: "YWRtaW4="
  erlang.cookie: "di96VHZ4VmhOY1Uxc3dzTG4zOHdyMmk2S1IrTG82L2xqUEdTTFUwYmdwVDRBPQ=="

Rbac.yaml:

apiVersion: v1
kind: ServiceAccount  #集群访问apiserver的凭证
metadata:
  name: rabbitmq
  namespace: test
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: endpoint-reader
  namespace: test
rules:
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get"]
---
kind: RoleBinding  #将角色绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: endpoint-reader
  namespace: test
subjects:
- kind: ServiceAccount
  name: rabbitmq
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: endpoint-reader

Statefulset.yaml:
要提前创建好挂载目录

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: rabbitmq
  namespace: test
spec:
  serviceName: rabbitmq-headless
  selector:
    matchLabels:
      app: rabbitmq  #在apps/v1中,需与 .spec.template.metadata.label 相同,用于hostname传播访问pod
  replicas: 3  #副本数3
  template:
    metadata:
      labels:
        app: rabbitmq
    spec:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - rabbitmq
              topologyKey: "kubernetes.io/hostname"
      serviceAccountName: rabbitmq
      terminationGracePeriodSeconds: 10
      containers:
      - name: rabbitmq
        image: rabbitmq:latest
        imagePullPolicy: Never
        resources:
          limits:
            cpu: 1
            memory: 500Mi
          requests:
            cpu: 1
            memory: 500Mi
        volumeMounts:
          - name: config-volume
            mountPath: /etc/rabbitmq
          - name: rabbitmq-data
            mountPath: /var/lib/rabbitmq/mnesia
        ports:
          - name: http
            protocol: TCP
            containerPort: 15672
          - name: amqp
            protocol: TCP
            containerPort: 5672
        livenessProbe:
          exec:
            command: ["rabbitmq-diagnostics", "status"]
          initialDelaySeconds: 60
          periodSeconds: 60
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command: ["rabbitmq-diagnostics", "status"]
          initialDelaySeconds: 20
          periodSeconds: 60
          timeoutSeconds: 5
        env:
        - name: RABBITMQ_DEFAULT_USER
          valueFrom:
            secretKeyRef:
              key: rabbitDefaulUser
              name: devsecret                     #登陆用户名和密码都存储在一个secret对象中
        - name: RABBITMQ_DEFAULT_PASS
          valueFrom:
            secretKeyRef:
              key: rabbitDefaultPass
              name: devsecret
        - name: RABBITMQ_ERLANG_COOKIE
          valueFrom:
            secretKeyRef:
              name: devsecret
              key: erlang.cookie
        - name: HOSTNAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: RABBITMQ_USE_LONGNAME
          value: "true"
        - name: K8S_SERVICE_NAME
          value: "rabbitmq-headless"
        - name: RABBITMQ_NODENAME
          value: rabbit@$(HOSTNAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.cluster.local
        - name: K8S_HOSTNAME_SUFFIX
          value: .$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.cluster.local
      volumes:
      - name: config-volume
        configMap:
          name: rabbitmq-config
          items:
          - key: rabbitmq.conf
            path: rabbitmq.conf
          - key: enabled_plugins
            path: enabled_plugins
      - name: rabbitmq-data
        hostPath:
          path: /root/rabbitmq/data
          type: Directory

Service.yaml

kind: Service
apiVersion: v1
metadata:
  name: rabbitmq-headless
  namespace: test
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
   - name: amqp
     port: 5672
   - name: http
     port: 15672
  selector:
    app: rabbitmq
    
---
kind: Service
apiVersion: v1
metadata:
  namespace: test
  name: rabbitmq-service
spec:
  ports:
  - name: http
    protocol: TCP
    port: 15672
    nodePort: 30672  #管理web界面
  - name: amqp
    protocol: TCP
    port: 5672
    targetPort: 5672
    nodePort: 30671
  selector:
    app: rabbitmq
  type: NodePort

5.3.2 申请资源清单(启动各个yaml文件)

kubectl apply -f rabbitmq-configmap.yaml
kubectl apply -f rabbitmq-secret.yaml
kubectl apply -f rabbitmq-rbac.yaml
kubectl apply -f rabbitmq-sts.yaml
kubectl apply -f rabbitmq-svc.yaml

在这里插入图片描述
5.3.3 访问Rabbirmq页面
http://ip:30672/尝试访问rabbitmq的web页面(需要手动创建用户并授权)
在这里插入图片描述

六、常用命令

  1. 用户管理
    A. 查看用户列表:rabbitmqctl list_users;
    B. 添加用户:rabbitmqctl add_user ;
    C. 修改密码:rabbitmqctl change_password ;
    D. 删除用户:rabbitmqctl delete_user ;
    E. 设置用户角色:rabbitmqctl set_user_tags <tag1,tag2>,角色有
    management:用户可以访问management管理插件;administrator:所有权限;
    monitoring:用户可以访问management管理插件,查看所有连接、通道以及与节点相关的信息;policymaker:用户可以访问management管理插件,并管理他们有权访问的vhost的策略和参数;
  2. 节点与应用管理
    A. 启动rabbitmq应用程序:rabbitmqctl start_app;
    B. 关闭rabbitmq应用程序,但Erlang VM保持运行:rabbitmqctl stop_app;
    C. 关闭所有应用和节点:rabbitmqctl stop;
    D. 将Rabbitmq节点返回到原始状态,包括删除数据:rabbitmqctl reset;
  3. 集群节点
    A. 查看集群状态:rabbitmqctl cluster_status;
    B. 添加节点:rabbitmqctl join_cluster {–ram|–disk} rabbit@node;
    C. 移除节点:rabbitmqctl forget_cluster_node rabbit@node,注意先关闭应用程序rabbitmqctl stop_app;
    D. 节点健康检查:rabbitmqctl node_health_check;
  4. 插件管理
    A. 显示所有插件:rabbitmq-plugins list;
    B. 启用指定的插件:rabbitmq-plugins enable rabbitmq_management rabbitmq_mqtt rabbitmq_prometheus;
  5. 查看有效配置
    A. rabbitmqctl environment

七、RabbitMQ配置详解

tcp_listeners	监听AMQP连接的端口或主机/对。
Default: [5672]
num_tcp_acceptors	Erlang进程的数量,接受TCP监听器的连接数。
Default: 10
handshake_timeout	对AMQP 0-8/0-9/0-9-1握手的最大时间(在套接字连接和SSL握手之后),以毫秒为间隔
Default: 10000
ssl_listeners	如上所述,用于SSL连接。
Default: []
num_ssl_acceptors	用于接受SSL监听连接的Erlang进程的数量。
Default: 1
ssl_options	SSL配置参数. 详情请看  SSL documentation.
Default: []
ssl_handshake_timeout	SSL握手超时,以毫秒为间隔。
Default: 5000
vm_memory_high_watermark	触发流控制的内存阈值。详情请看  memory-based flow control.
Default: 0.4
vm_memory_high_watermark_paging_ratio	设置当内存使用超过总内存百分比多少时,队列开始将消息持久化到磁盘以释放内存。 详情请看  memory-based flow control.
Default: 0.5
disk_free_limit	RabbitMQ存储数据的分区的磁盘空间限制。当可用的磁盘空间低于这个限制时,就会触发流控制。值可以相对于RAM的总数设置(例如,内存比例,1.0)。该值也可以设置为整数的字节数。或者,单位(例如“50 mb”)。默认情况下,空闲磁盘空间必须超过50MB。详情请看  Disk Alarms.
Default: 50000000
log_levels	控制日志的粒度。该值是一个日志事件类别和日志级别对的列表。
可设置级别:
  'none'
  'error'
  'warning'
  'info' 
  'debug' 
  以上下一层级别的日志输出均包含上层级别日志输出(如: warning包含warning和error), none为不输出日志
另外,当前未分类的事件总是记录在日志中
The categories are:
channel - 所有与AMQP通道有关的事件
connection - 对于所有与网络连接有关的事件
federation - 对于所有与 federation有关的事件
mirroring - 对于与镜像队列相关的所有事件
Default: [{connection, info}]

frame_max	
框架最大允许大小(以字节为单位)与消费者进行数据交换。设置为0意味着“无限”,但会在一些QPid客户端触发一个bug。
设置更大的值可能会提高吞吐量;
设置较小的值可能会提高延迟。
Default: 131072

channel_max	
与消费者进行谈判的最大允许数量。设置为0意味着“无限”。
使用更多的通道会增加代理的内存占用。
Default: 0

channel_operation_timeout	通道操作超时为毫秒(内部使用,由于消息传递协议的差异和限制而不直接暴露于客户机)。
Default: 15000

heartbeat	
该值表示服务器在连接中发送的心跳延迟,在几秒钟内。优化框架。如果设置为0,则会禁用心跳。客户端可能不会遵循服务器的建议,请参阅AMQP参考以了解更多细节。
在有大量连接的情况下,禁用心跳可能改善性能,但可能会导致连接在关闭非活动连接的网络设备的出现。
Default: 60 (580 prior to release 3.5.5)

default_vhost	当RabbitMQ创建一个新的数据库时,创建一个虚拟主机。交换amq.rabbitmq.logwill存在于这个虚拟主机中。
Default: <<"/">>

default_user	当RabbitMQ从头创建一个新数据库时,要创建用户名。 
Default: <<"guest">>

default_pass	默认用户的密码。
Default: <<"guest">>

default_user_tags	默认用户的标记。
Default: [administrator]

default_permissions	在创建时分配给默认用户的权限。
Default:  [<<".*">>, <<".*">>, <<".*">>]

loopback_users	
只允许通过环回接口连接到代理的用户列表(即localhost)。 如果您希望允许缺省的来宾用户远程连接,则需要将其更改为 [].
Default:  [<<"guest">>]

cluster_nodes	当一个节点开始第一次启动时,将它设置为使集群自动发生。元组的第一个元素是节点试图集群到的节点。第二个元素是磁盘或ram,并确定节点类型。
Default: {[], disc}

server_properties	键值对的列表,在连接上向客户端宣布。
Default: []

collect_statistics	统计数据收集模式。主要与管理插件有关。选项有:
none (不要发布统计数据)
coarse (发出每个队列/每个通道/每个连接统计信息)
fine (发出的每条数据)
通常情况下不需要设置该参数
Default: none

collect_statistics_interval	统计数据收集间隔以毫秒为间隔。 主要相关插件  management plugin.
Default: 5000

management_db_cache_multiplier	管理插件将缓存诸如队列清单之类的代价较高的查询的时间。缓存将把最后一个查询的运行时间乘以这个值,并在此时间内缓存结果。
Default: 5

auth_mechanisms	 提供给客户端的SASL身份验证机制。
Default: ['PLAIN', 'AMQPLAIN']

auth_backends	
要使用的身份验证和授权后端列表。
rabbit\u auth\u backend\u Internal之外的其他数据库可以通过插件获得。Default: [rabbit_auth_backend_internal]

reverse_dns_lookups	设置为true,让RabbitMQ对客户端连接执行反向DNS查找,并通过rabbitmqctl和管理插件呈现该信息。
Default: false

delegate_count	用于集群内部通信的委托进程的数量。当为多核CPU时可以考虑设置该值
Default: 16

trace_vhosts	Used internally by the  tracer. 通常情况下不需要设置该参数
Default: []

tcp_listen_options	默认的套接字选项。通常情况下不需要设置该参数
Default:

[{backlog,       128},
 {nodelay,       true},
 {linger,        {true,0}},
 {exit_on_close, false}]
 
hipe_compile	设置为true,使用HiPE预编译RabbitMQ的部分,这是Erlang的即时编译器。这将增加服务器的吞吐量,以增加启动时间的成本。
您可能会看到,在启动时延迟几分钟,您的性能会提高20-50%。这些数据是高度工作负载和硬件依赖的。
HiPE支持可能不会编译到您的Erlang安装中。如果不是这样,启用这个选项只会导致一个警告消息被显示,而启动将照常进行。例如,Debian/Ubuntu用户需要安装erlangbase-base-hipe包。
HiPE在某些平台上是不可用的,尤其是Windows。
HiPE在17.5之前就已经知道了erlangp/otp版本的问题。HiPE推荐使用最新的erlangp/otp版本
Default: false

cluster_partition_handling	如何处理网络分区。可用模式: 
ignore
pause_minority
{pause_if_all_down, [nodes], ignore | autoheal}
(例: ['rabbit@node1', 'rabbit@node2'])
autoheal
Default: ignore

cluster_keepalive_interval	节点应该多频繁地将keepalive消息发送到其他节点(以毫秒为单位)。请注意,这与netticktime不一样; 错过的keepalive消息不会导致节点被认为挂机。
Default: 10000

queue_index_embed_msgs_below	在消息的字节数中,消息将被直接嵌入到队列索引中。详情请看  persister tuning
Default: 4096

msg_store_index_module	用于队列索引的实现模块。 详情请看  persister tuning
Default: rabbit_msg_store_ets_index

backing_queue_module	队列内容的实现模块。通常情况下不需要设置该参数
Default: rabbit_variable_queue

msg_store_file_size_limit	Tunable value for the persister.  通常情况下不需要设置该参数
Default: 16777216

mnesia_table_loading_retry_limit	在等待集群中的Mnesia tables可用时,需要重试的次数。
Default: 10

mnesia_table_loading_retry_timeout	在集群中等待每个重试的时间,以便可用
Default: 30000

queue_index_max_ journal_entries	Tunable value for the persister.  通常情况下不需要设置该参数
Default: 65536

queue_master_locator	
Queue master定位策略

可用策略:
<<"min-masters">>
<<"client-local">>
<<"random">>
详情请看  documentation on queue master location
Default: <<"client-local">>

lazy_queue_explicit_gc_run_operation_threshold	
调优: 只有在内存压力下有延迟队列时。
这是触发垃圾收集器和其他内存减少活动的阈值。一个低的值可以降低性能,一个高的值可以提高性能,但是会导致更高的内存消耗。通常情况下不需要设置该参数
Default: 1000

queue_explicit_gc_run_operation_threshold	
调优: 在内存压力较大时。
这是触发垃圾收集器和其他内存减少活动的阈值。一个低的值可以降低性能,一个高的值可以提高性能,但是会导致更高的内存消耗。通常情况下不需要设置该参数
Default: 1000

八、RabbitMQ优化

8.1、加大服务器带宽

访问量大时,较长的数据容易将带宽占满。如服务器上传带宽为10M,则实际上传带宽可认为1M,每秒上传量为1M/1K=1K。如果把带宽加到100M,则每秒上传量为10K。一般情况下,RabbitMq服务器能够接受的每秒写入量为20K-50K(8G内存),因此在带宽在不足200M的时候,加大带宽会产生很明显的提升作用,再往上效果就可能不那么明显了。

8.2、加大内存

RabbitMq的机制是先将消息放在内存中,然后分批写入硬盘。小批量数据的写入基本上都放在内存中,内存数据量过大时会一边把客户端的数据往内存里写,一边将内存里的陈旧数据往硬盘里写,这样会对速度造成较严重的损耗。适度的增加内存,队列将会更多的消息放在内存中,增加系统的处理速度。

8.3、使用固态硬盘

机械硬盘的写入速度较慢,处理大量数据时机械硬盘对性能的损耗十分严重。如果要存放1亿条数据,所需要的硬盘大小为100G,建议采用100-500G固态硬盘。再加上消费端在不断的处理数据,一般待处理的消息能够达到千万级别已经相当不容易了

8.4、增加生产者

服务器可以建立多个连接,单个生产者往往不能充分利用服务器的潜能,建立多个生产者之后,服务器处理能力将会得到充分利用。一般情况下,一个生产者每秒可以传入1000-5000条消息,在1-10这个范围内,每增加一个生产者,处理速度就会相对单生产者增加一倍

8.5、增加消费者

消费者增多时,出队速度有明显改善。该方案对于出队速度的影响有限,1-10个进程范围内,相对于单进程只有一倍左右的提升,建议线程开2-5个即可,再多可能影响不大。出现该现象的原因可能是服务器带宽或硬件处理能力有限,消费者增加了也没什么用处。因为没有实际环境测试,此条只列为建议,采用前可以多做实验

8.6、改网络访问为本地访问

该方案在消费端/生产端与RabbitMq服务器部署在同一台电脑时有用,因为省略了网络传输,大大节省了处理时间。如果消费端/生产端与RabbitMq服务器分开部署,该方案就不能使用了。在代码中将IP地址127.0.0.1改为localhost即可

8.7、消费端使用长连接

如果每次消费都建立一个连接,无疑将极大的消耗网络与消费端资源,可以只建立一个长链接,所有消息都使用这个长连接来消费。此处需要注意的是,如果长连接出问题,可能会导致队列不能继续消费,需要注意做异常控制。

8.8、消息不要超过4M

消息包大小由1K到10MB,当包大小达到4.5MB时,服务器的性能出现明显的异常,传输率尤其是每秒订阅消息的数量,出现波动,不稳定;同时有一部分订阅者的TCP连接出现断开的现象。可能是客户端底层或者RabbitMQ服务端在进行拆包,组包的时候,出现了明显的压力,而导致异常的发生

九、监控

可以通过接口 来获取性能指标
http://ip:15672/api/nodes
http://IP:15672/api/queues
http://IP:15672/api/overview

通过rabbitmq_exporter来获取RabbitMQ监控指标

获取节点信息的API:
GET /api/nodes/{node} 返回单个节点的状态
GET /api/nodes 返回所有集群成员的统计信息

指标JSON field name
使用的内存总量memory usedmem_used
内存使用阈值mem_limit
当内存使用超过阈值时将触发报警memory alarmmem_alarm
剩余磁盘空间阈值disk_free_limit
当空闲磁盘空间低于配置的限制时,将触发报警disk_free_alarm
可用文件描述符总数fd_total
当前使用的文件描述符fd_used
尝试打开的文件描述符数量io_file_handle_open_attempt_count
socket可用sockets_total
已经使用的socket数量sockets_used
Message store disk readsmessage_stats.disk_reads
Message store disk writesmessage_stats.disk_writes
Inter-node communication linkscluster_links
GC runsgc_num
gc回收的字节gc_bytes_reclaimed
erlang进程限制proc_total
已经使用erlang进程proc_used
正在运行的队列run_queue

可以从任一节点获取集群监控数据
API:GET /api/overview

指标JSON field name
集群名称cluster_name
集群范围的消息速率message_stats
连接总数object_totals.connections
channel总数object_totals.channels
队列总数object_totals.queues
消费者总数object_totals.consumers
消息总数(ready+unacked)queue_totals.messages
准备交付的消息数量queue_totals.messages_ready
未确认的消息数量queue_totals.messages_unacknowledged
最近发布的消息数量message_stats.publish
消息发布的速率message_stats.publish_details.rate
最近发送给消费者的消息数量message_stats.deliver_get
消息交付速率message_stats.deliver_get.rate

单个队列监控API地址: GET /api/queues/{vhost}/{qname}

指标JSON field name
内存memory
消息总数(ready+unacknowledged)messages
准备交付的消息数量messages_ready
未确认的消息数量messages_unacknowledged
最近发布的消息数量message_stats.publish
消息发布速度message_stats.publish_details.rate
最近交付的消息数量message_stats.deliver_get
消息交付速度message_stats.deliver_get.rate
其他消息状态 this documentmessage_stats

整理监控指标情况

监控项指标名称阈值
rabbitmq节点状态rabbitmq-status!= 1 紧急
rabbitmq节点内存使用率rabbitmq-node_mem_used> 0.8中度
>0.9严重
rabbitmq文件句柄数使用率rabbitmq_fd_used> 0.8中度
>0.9严重
rabbitmq堆积消息监控rabbitmq_queue_messages_unack> 500中度
> 1000严重
rabbitmq推送错误监控rabbitmq_failed_to_publish_total>5中度
rabbitmq可消费消息数监控rabbitmq_queue_messages_ready> 5000中度
rabbitmq推送消息监控rabbitmq_queue_messages_published_total==0中度
rabbitmq消息投递监控rabbitmq_queue_messages_delivered_total==0中度
rabbitmq消息连接恢复rabbitmq_connection_recovery_total>10中度
rabbitmq消息连接数rabbitmq_connections==0严重
rabbitmq通道rabbitmq_channel==0严重
rabbitmq消费者rabbitmq_consumers==0严重
rabbitmq的sockets使用率rabbitmq_sockets_used> 0.8中度
>0.9严重

十、常见故障与排查

RabbitMQ注意小计(故障恢复提示):

  1. 保证集群中至少有一个磁盘类型的节点以防数据丢失,在更改节点类型时尤其要注意。
  2. 若整个集群被停掉了,应保证最后一个down掉的节点被最先启动,若不能则要使用forget_cluster_node命令将其移出集群。
  3. 若集群中节点几乎同时以不可控的方式down 了,此时再其中一个节点使用force_boot 命令重启节点。
  4. 如果加入集群后,意外关闭等造成rabbitmq-server启动不成功,可以尝试一下步骤:/var/lib/rabbitmq/mnesia 目录下存在rabbit@localhost.pid、rabbit@localhost、rabbit@localhost-plugins-expand,删除这3项后,并且删除 /var/lib/rabbitmq/ 目录下 .erlang.cookie和erl_crash.dump 再使用systemctl start rabbitmq-server启动

10.1、消费慢

问题分析:
可以看到RabbitMQ的内存 占用占用已经使用了7.8G 允许的值为 .6G左右
因为 vm_memory_high_watermark 值设置的是0.4 也就是物理内存的40% ;服务器为16G * 40% = 6.4G
一般在产生的原因是长期的生产者发送速率大于消费者消费速率导致. 触发了RabbitMQ 的流控;
解决方案:

  1. 增加消费者端的消费能力,或者增加消费者(根本解决)
  2. 控制消息产生者端的发送速率(不太现实)
  3. 增加mq的内存(治标不治本)

10.2、消息丢失

这个是RabbitMQ最常见的问题,RabbitMQ丢失分三种情况,生产者消息丢失,RabbitMQ消息丢失,消费者消息丢失.

  1. 生产者消息丢失
    生产者在发送消息给RabbitMQ,在中途有可能因为网络问题导致消息丢失,我们可以选择RabbitMQ提供的事务,也可以用confirm模式,就是生产者确认
    事务:
    channel.tsSelect开启事务;
    channel.txRollback出现问题事务回滚
    channel.txCommit成功后提交事务
    confirm模式:
    生产者发送消息,每个消息分配一个id,如果RabbitMQ接收到消息返回ack,如果没有收到放回nack,这个时候生产者只需要重新发送这个消息即可,可以结合这个机制在内存里设置消息id的状态,多长时间没有f返回ack就是失败,重新发送消息.
    事务和confirm对比:
    事务是属于同步的,在你提交一个事务会阻塞在那里,其他的消息是不能继续发送的,这样很容易影响性能,而confirm是异步的就是发送完我可以继续发送另一条消息,在正常使用中推荐使用confirm模式
  2. RabbitMQ消息丢失
    RabbitMQ数据丢失,可以用持久化分为两个步骤:
    首选创建queue的时候将其设置为持久化,这样可以保证RabbitMQ持久化queue的元数据,而不会持久化queue的数据,第二步将消息的deliveryMode设置为2,就是将消息设置为持久化,此时消息就会持久化到磁盘上,即使RabbitMQ重启,也会从磁盘上恢复queue,恢复queue里的数据
    跟生产者的confirm配合,如过持久化到磁盘上再返回ack,如果还没持久化就RabbitMQ挂掉了,生产者没有收到ack,还是会重新发送消息.
  3. 消费者消息丢失
    消费者有可能因为刚接到消息还没有处理就重启了,但是RabbitMQ以为他处理了,这样就会导致消息丢失,合理的解决方案是关闭自动ack,可以通过api来进行调用,等自己的代码处理完成之后,可以ack,这样即使你没有消费RabbitMQ也知道你是没有去消费的,这个时候RabbitMQ可以把消息交给其他的consumer进行消费,避免消息丢失

10.3、消息重复消费

出现原因:消费者消息消息的时候,MQ没有收到消息的ack应答。
场景:

  1. 消费者消费消息后没有ack。
  2. 消费者在消费消息后,ack时网络异常。

解决步骤:

  • 消费者消费后,记录通过缓存记录消息的消费标识,消息id如redis的setnx
  • 如果消费成功且ack成功,则删除记录的消息标记。
  • 如果ack失败,消息下次被消费消息时候,先去查询消息的消费标识,已经消费则直接ack,未消费则继续消费。

10.4、报错“error in config file “/etc/rabbitmq/rabbitmq.config” (none): no ending found”

rabbitmq config的配置相关的官方文档: http://www.rabbitmq.com/configure.html 官方给出的一个 示例配置: https://github.com/rabbitmq/rabbitmq-server/blob/v3.8.x/deps/rabbit/docs/rabbitmq.conf.example 拷贝以上实例文档 到 对应的rabbitmq的安装目录下的文件:/etc/rabbitmq , 取名配置文件名称为 rabbitmq.config,重启rabbit,那么当前文件 就为 当前rabbit所使用。

10.5、生产者发送消息报错

channel is already closed due to channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - home node ‘rabbit@xxx’ of durable queue ‘xxx_queue’ in vhost ‘/’ is down or inaccessible, class-id=50, method-id=10)
生产者连接不上vhost’/',看报错像是服务端有问题,经排查后发现,发现服务集群有一个节点满了,导致连接到这个节点的Connection都出问题了。
解决方案:添加节点,重启生产者服务。

10.6、浏览器打开IP地址,无法访问 RabbitMQ(白屏没有结果)

服务器对应的安全组15672端口没有开启(入规则),导致浏览器无法访问到服务器的任何内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250773.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《白帽子讲Web安全》15-16章

《白帽子讲Web安全》15-16章 《白帽子讲Web安全》15章15、Web Server配置安全15.1、Apache安全15.2、Nginx安全15.3、jBoss远程命令执行15.4、Tomcat远程命令执行15.5、HTTP Parameter Pollution15.6、小结 第四篇 互联网公司运营安全《白帽子讲Web安全》16章16、互联网业务安全…

使用R语言进行美国失业率时空分析(包括绘图)

今天写一篇利用R语言&#xff0c;针对面板数据的简单分析与绘图。让我们直接开始把。 一、数据准备 这次的示例数据非常简单&#xff0c;只有一个shp格式的美国区县矢量数据&#xff0c;我们在QGIS中打开数据查看一下它的属性表。事实上我们需要的数据都在属性表的字段中。 二…

计算机毕业设计Python+LSTM天气预测系统 AI大模型问答 vue.js 可视化大屏 机器学习 深度学习 Hadoop Spark

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

YOLOv8实战无人机视角目标检测

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对无人机目标数据集进行训练和优化&#xff0c;该数据集包含丰富的无人机目标图像…

uniapp App端在renderjs层渲染echarts获取不到service层id的问题

报错信息&#xff1a;Cannot read properties of undefined (reading id) at app-view.js 这样的写法App端有时在renderjs视图层获取不到server逻辑层的数据 server层 renderjs层 解决方法&#xff1a;需要把数据(id)通过server层向renderjs层传值 server层 renderjs层

【数据湖仓】-- 阿里云 EMR 和 AWS EMR 工具对比

目录 1. 基础设施和集成生态 阿里云 EMR: AWS EMR: 2. 性能与可扩展性 阿里云 EMR: AWS EMR: 3. 成本对比 阿里云 EMR: AWS EMR: 4. 易用性和用户体验 阿里云 EMR: AWS EMR: 5. 总结对比 阿里云 EMR(Elastic MapReduce)和 AWS EMR(Amazon Elas…

Ubuntu在NVME硬盘使用Systemback安装记录

问题 使用Systemback重装系统找不到NVME硬盘。 0.使用Systemback制作iso后&#xff0c;制作启动盘 1.插入启动盘进入live mode模式 2.安装gparted sudo apt-get update sudo apt-get install gparted3.使用gparted对待分区硬盘进行分区 gparted按照你希望的分区方式分区即…

BUUCTF—Reverse—GXYCTF2019-luck_guy(9)

下载附件&#xff0c;照例扔入Exeinfo PE查看信息 可执行文件&#xff0c;IDA 64位直接干 进main函数&#xff0c;F5反编译&#xff0c;看主要处理函数&#xff0c;跳转进去 查看&#xff0c;点进patch_me(v4)看看是怎么回事 这里已经相当清楚&#xff0c;逻辑就是如果你输入的…

Kubernetes KubeVirt 让容器和虚拟机一起工作

在不讨论容器与虚拟机的优缺点的情况下&#xff0c;每个虚拟机或都包含其完整操作系统的实例&#xff0c;并且可以像独立服务器一样运行。相比之下&#xff0c;在容器化环境中&#xff0c;多个容器共享一个操作系统实例&#xff0c;而且绝大多数都是类Linux操作系统。 并非所有…

新型大语言模型的预训练与后训练范式,谷歌的Gemma 2语言模型

前言&#xff1a;大型语言模型&#xff08;LLMs&#xff09;的发展历程可以说是非常长&#xff0c;从早期的GPT模型一路走到了今天这些复杂的、公开权重的大型语言模型。最初&#xff0c;LLM的训练过程只关注预训练&#xff0c;但后来逐步扩展到了包括预训练和后训练在内的完整…

【解决安全扫描漏洞】---- 检测到目标站点存在 JavaScript 框架库漏洞

1. 漏洞结果 JavaScript 框架或库是一组能轻松生成跨浏览器兼容的 JavaScript 代码的工具和函数。如果网站使用了存在漏洞的 JavaScript 框架或库&#xff0c;攻击者就可以利用此漏洞来劫持用户浏览器&#xff0c;进行挂马、XSS、Cookie劫持等攻击。 1.1 漏洞扫描截图 1.2 具体…

python爬虫案例精讲:爬取豆瓣电影Top250信息

前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;BeautifulSoup库来解析HTML页面&#xff0c;并将数据存储到CSV文件中。这个爬虫将自动获取豆瓣电影Top250页面的信息&#xff0c;包括电影名…

Node.js的url模块与querystring模块

新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;&#xff08;Web前端技术丛书&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 4.3.1 http模块——创建HTTP服务器、客户端 要使用http模块&#xff0…

Vue0-生命周期-03

生命周期 生命周期指定就是一个对象从创建到销毁的整个过程。 Vue也是有的 完整的Vue周期包含8个阶段。 Vue官方生命周期流程图&#xff1a; 那这有什么用呢&#xff1f;我们可以在指定阶段做特殊的事件。 这些方法伴随生命周期的进行自动执行。 <!DOCTYPE html> <…

【0346】Postgres内核 Startup Process 通过 signal 与 postmaster 交互实现 (5)

1. Startup Process 进程 postmaster 初始化过程中, 在进入 ServerLoop() 函数之前,会先通过调用 StartChildProcess() 函数来开启辅助进程,这些进程的目的主要用来完成数据库的 XLOG 相关处理。 如: 核实 pg_wal 和 pg_wal/archive_status 文件是否存在Postgres先前是否发…

【Git 工具】用 IntelliJ IDEA 玩转 Git 分支与版本管理

文章目录 一、使用 IDEA 配置和操作 Git1.1 查看 Idea 中的 Git 配置1.2 克隆 Github 项目到本地 二、版本管理2.1 提交并推送修改2.2 拉取远程仓库2.3 查看历史2.4 版本回退 三、分支管理3.1 新建分支3.2 切换分支3.2 合并分支3.4 Cherry-Pick 参考资料 一、使用 IDEA 配置和操…

利用dockerCompose一键部署前后端分离项目

1.Docker Compose介绍 2.将自己准备好的docker-compose.yml文件上传到宿主机 3.查看docker-compose.yml文件 宿主机的文件内容可参考&#xff1a; 项目部署-通过docker手动部署前后端分离项目&#xff08;全网超级详细 的教程&#xff09;-CSDN博客 修改宿主机的nginx.conf …

Flink四大基石之Time (时间语义) 的使用详解

目录 一、引言 二、Time 的分类及 EventTime 的重要性 Time 分类详述 EventTime 重要性凸显 三、Watermark 机制详解 核心原理 Watermark能解决什么问题,如何解决的? Watermark图解原理 举例 总结 多并行度的水印触发 Watermark代码演示 需求 代码演示&#xff…

解决SpringBoot连接Websocket报:请求路径 404 No static resource websocket.

问题发现 最近在工作中用到了WebSocket进行前后端的消息通信&#xff0c;后端代码编写完后&#xff0c;测试一下是否连接成功&#xff0c;发现报No static resource websocket.&#xff0c;看这个错貌似将接口变成了静态资源来访问了&#xff0c;第一时间觉得是端点没有注册成…

(超详细图文)PLSQL Developer 配置连接远程 Oracle 服务

1、下载配置文件 &#xff08;超详细图文详情&#xff09;Navicat 配置连接 Oracle-CSDN博客 将下载的文件解压到单独文件夹&#xff0c;如&#xff1a;D:\App\App_Java\Oracle\instantclient-basic-windows.x64-19.25.0.0.0dbru 2、配置 打开 PLSQL Developer&#xff0c;登…