1. 配置文件

RabbitMQ存在默认的配置,该配置在测试环境、开发环境或者低负载的生产环境一般没有问题,但是对于有较高负载的生产环境很可能不适合,需要进行进一步的优化的调整。

1.1. 配置文件介绍

配置文件查看,可以通过 rabbitmq-diagnostics status 查看,默认的情况下,可能为空。日志的顶行也同样会显示。

  1. root@ubuntu-7-61:~# rabbitmq-diagnostics status
  2. ...
  3. Plugins
  4. Enabled plugin file: /etc/rabbitmq/enabled_plugins
  5. Enabled plugins:
  6. * rabbitmq_prometheus
  7. * prometheus
  8. * rabbitmq_management
  9. * amqp_client
  10. * rabbitmq_web_dispatch
  11. * cowboy
  12. * cowlib
  13. * rabbitmq_management_agent
  14. Data directory
  15. Node data directory: /var/lib/rabbitmq/mnesia/rabbit@ubuntu-7-61
  16. Raft data directory: /var/lib/rabbitmq/mnesia/rabbit@ubuntu-7-61/quorum/rabbit@ubuntu-7-61
  17. Config files
  18. Log file(s)
  19. * /var/log/rabbitmq/rabbit@ubuntu-7-61.log
  20. * /var/log/rabbitmq/rabbit@ubuntu-7-61_upgrade.log

rabbitmq 的配置文件分两种格式类型:一种是类似于 ini 格式,也被称为sysctl格式(key=value);另一种是比较复杂的经典格式。其中配置文件分类有三种:

配置文件名称 风格 描述
rabbitmq.conf ini 类型格式 主配置文件,绝大部分配置都可以采用这种格式。 # 开头为注释。3.7版本开始使用。示例
advanced.config 经典格式(erlang格式) 一些ini格式无法描述的配置,如LDAP配置。 %% 开头为注释。示例
rabbitmq-env.conf 环境变量键值对 设置rabbitmq的环境变量

以下是两种配置文件的格式对比:

# A new style format snippet. This format is used by rabbitmq.conf files.
ssl_options.cacertfile           = /path/to/ca_certificate.pem
ssl_options.certfile             = /path/to/server_certificate.pem
ssl_options.keyfile              = /path/to/server_key.pem
ssl_options.verify               = verify_peer
ssl_options.fail_if_no_peer_cert = true
%% A classic format snippet, now used by advanced.config files.
[
  {rabbit, [{ssl_options, [{cacertfile,           "/path/to/ca_certificate.pem"},
                           {certfile,             "/path/to/server_certificate.pem"},
                           {keyfile,              "/path/to/server_key.pem"},
                           {verify,               verify_peer},
                           {fail_if_no_peer_cert, true}]}]}
].

以下是配置文件的位置

Platform Default Configuration File Directory Example Configuration File Paths
Generic binary package $RABBITMQ_HOME/etc/rabbitmq/ $RABBITMQ_HOME/etc/rabbitmq/rabbitmq.conf
$``RABBITMQ_HOME/etc/rabbitmq/advanced.config
Debian and Ubuntu /etc/rabbitmq/ /etc/rabbitmq/rabbitmq.conf
/etc/rabbitmq/advanced.config
RPM-based Linux /etc/rabbitmq/ /etc/rabbitmq/rabbitmq.conf
/etc/rabbitmq/advanced.config

需要注意的是,以下三个环境变量会覆盖默认的配置文件位置

  • RABBITMQ_CONFIG_FILE
  • RABBITMQ_ADVANCED_CONFIG_FILE
  • RABBITMQ_CONF_ENV_FILE

    1.2. 常用配置项

    1.2.1. 网络配置

    RabbitMQ的Server和Client之间通过TCP进行通信,网络配置调整对RabbitMQ的性能影响比较大,也是操作最多的方面,详情可以参考官方文档

    1.2.1.1. 配置端口监听

  • RabbitMQ的默认端口分配

    4369            # RabbitMQ节点和CLI工具使用的对等发现服务
    5671,5672       # AQMP通信地址,前者非TLS,后者TLS
    25672           # 用于节点间和CLI工具通信(Erlang分发服务器端口),并从动态范围分配
    35672-35682     # 由CLI工具(Erlang分发客户端端口)用于与节点进行通信
    15672           # 管理台端口(仅在启用了对应插件的前提下)
    15674           # STOMP-over-WebSockets 客户端(仅在启用了对应插件的前提下)
    15675           # MQTT-over-WebSockets 客户端(仅在启用了对应插件的前提下)
    15692           # Prometheus metrics 端口(仅在启用了对应插件的前提下)
    1883,8883       # MQTT客户端,前者非TLS,后者TLS(仅在启用了对应插件的前提下)
    61613,61614     # STOMP客户端,前者非TLS,后者TLS(仅在启用了对应插件的前提下)
    
  • 常用配置 ```

    TCP 监听地址配置

    listeners.tcp.default = 5672 # 默认监听地址 listeners.tcp.1 = 192.168.1.99:5672 # 监听指定的IP listeners.tcp.1 = 0.0.0.0:5672 # 监听所有IPv4地址 listeners.tcp.2 = ::1:5672 # 监听所有IPv6地址 listeners.tcp = none # 关闭非TLS端口

TLS 配置(默认关闭)

listeners.ssl.default = 5671 ssl_options.cacertfile = /path/to/ca_certificate.pem ssl_options.certfile = /path/to/server_certificate.pem ssl_options.keyfile = /path/to/server_key.pem ssl_options.verify = verify_peer ssl_options.fail_if_no_peer_cert = false

<a name="MhfEg"></a>
#### 1.2.1.2. 优化吞吐量
该场景是指,客户端连接的数量并不多,但是单个客户端发布和消费的消息数量非常大,此时需要优化单个连接的吞吐量

- 增加 TCP buffer 大小
- 禁用Nagle的算法(系统调优)
- 启用可选的TCP功能和扩展(系统调优)

AMQP 连接配置

tcp_listen_options.backlog = 128 tcp_listen_options.nodelay = true tcp_listen_options.linger.on = true tcp_listen_options.linger.timeout = 0 tcp_listen_options.sndbuf = 196608 # 增加缓冲区大小,单位 Byte tcp_listen_options.recbuf = 196608

```
# MQTT
mqtt.tcp_listen_options.backlog = 128
mqtt.tcp_listen_options.nodelay = true
mqtt.tcp_listen_options.linger.on = true
mqtt.tcp_listen_options.linger.timeout = 0
mqtt.tcp_listen_options.sndbuf = 196608
mqtt.tcp_listen_options.recbuf = 196608
# STOMP
stomp.tcp_listen_options.backlog = 128
stomp.tcp_listen_options.nodelay = true
stomp.tcp_listen_options.linger.on = true
stomp.tcp_listen_options.linger.timeout = 0
stomp.tcp_listen_options.sndbuf = 196608
stomp.tcp_listen_options.recbuf = 196608

1.2.1.3. 优化大量连接

与高吞吐量的场景不同,在某些情况下,大量的服务连接MQ,但是每个连接的消息量很少,此时需要调整配置,允许连接更多的客户端连接。

  • 增加打开的文件描述符数量
  • 减少单个连接的内存使用量
  • 减少单个增加CPU使用率
  • 允许更多的Erlang进程数量处理连接 ```

    AMQP

    tcp_listen_options.backlog = 4096 # 增加全连接的队列长度, 需要先调整 net.core.somaxconn 才能生效,系统默认128 tcp_listen_options.nodelay = true tcp_listen_options.linger.on = true tcp_listen_options.linger.timeout = 0 tcp_listen_options.sndbuf = 32768 tcp_listen_options.recbuf = 32768 # 减少缓冲区大小

MQTT

mqtt.tcp_listen_options.backlog = 4096 mqtt.tcp_listen_options.nodelay = true mqtt.tcp_listen_options.linger.on = true mqtt.tcp_listen_options.linger.timeout = 0 mqtt.tcp_listen_options.sndbuf = 32768 mqtt.tcp_listen_options.recbuf = 32768

STOMP

stomp.tcp_listen_options.backlog = 128 stomp.tcp_listen_options.nodelay = true stomp.tcp_listen_options.linger.on = true stomp.tcp_listen_options.linger.timeout = 0 stomp.tcp_listen_options.sndbuf = 32768 stomp.tcp_listen_options.recbuf = 32768

```
collect_statistics_interval = 60000  # 减少metrics接口数据刷新速度(ms),默认 5000
channel_max = 4                      # 减少单个连接允许的channel 数量,默认 16

1.2.1.4. 优化频繁开关连接

部分场景中,会频繁有连接开启和关闭,可能导致系统连接耗尽,或者出现大量的timewait。

  • 增加打开的文件描述符数量
  • 允许更多的Erlang进程数量处理连接
  • 降低心跳的检测周期,默认为60s,
  • 增加内核中允许的临时端口范围(客户端)
  • 减少允许的time_wait状态的连接数峰值(客户端)

    1.2.2. 内存使用

    内存使用的情况查询:https://rabbitmq.com/memory-use.html#breakdown-cli

    1.2.3. 日志配置

    在RabbitMQ 3.7之前,日志分别记录到两个文件,一个是一般Message日志,一个是未处理的异常日志,在3.7之后仅保留一个日志文件,可以通过 rabbitctl status 或者 rabbitmq-diagnostics status 查看日志路径,日志文件位置配置可以通过 sysctl 格式配置文件配置,也可以通过环境变量 RABBITMQ_LOGS 配置, RABBITMQ_LOGS=- 表示日志输出到标准输出。

    1.2.3.1. 日志基础配置项

    使用apt或者yum安装的RabbitMQ,默认使用的是系统 logroate 进行日志切割,默认配置在 /etc/logrotate.d/rabbitmq-server 。处理日志输出到文件之外,还支持输出到控制台或者syslog,详细可以查阅官方文档

    log.file = false                    # 关闭文件日志,默认开启
    log.dir = /data/logs/rabbitmq       # 日志存放目录
    log.file = rabbit.log               # 日志文件名
    log.file.level = info               # 日志级别;debug,info,warning,error,critical
    log.file.rotation.date = $D0        # 按时间切割($D0表示每天零点,$H00表示每小时零分)
    log.file.rotation.size = 10485760   # 按大小切割(单位 Byte)
    log.file.rotation.count = 5         # 保留的日志副本数
    

    1.2.3.2. 日志分类

    上述的日志配置,是让所有日志输出到同一个文件,在生产环境中,可能我们会比较关注某一类日志,从而需要将其从 log.file 中筛选出来,存入特定的文件中,并为它配置特定的日志级别。RabbitMQ日志分为以下几个类型:

    connection      AMQP连接生命周期事件日志
    channel         channel日志,通常为AMQP channel 的错误和警告
    queue           queue日志,一般为debug消息,日志输出很少
    mirroring       镜像队列日志
    federation      federation插件日志
    upgrade         版本升级日志
    default         其他类型日志
    
    日志分类配置方式
    log.<category>.level = info  # 会覆盖默认的级别
    log.<category>.file  = <category>.log
    

    以下是配置 connection 日志的案例:

    root@ubuntu-7-60:~# cat /etc/rabbitmq/rabbitmq.conf
    log.dir = /var/log/rabbitmq
    log.file = rabbitmq.log
    log.file.level = info
    log.file.rotation.size = 67108864
    log.file.rotation.count = 3
    log.connection.file = connection.log
    log.channel.file = channel.log
    

    配置之后的,通过程序测试连接 rabbitmq,然后异常断开

    root@ubuntu-7-60:/var/log/rabbitmq# cat connection.log
    2021-02-06 06:04:58.304 [info] <0.272.0> Log file opened with Lager
    2021-02-06 06:05:18.550 [info] <0.963.0> accepting AMQP connection <0.963.0> (10.4.7.1:54778 -> 10.4.7.60:5672)
    2021-02-06 06:05:18.552 [info] <0.963.0> connection <0.963.0> (10.4.7.1:54778 -> 10.4.7.60:5672): user 'admin' authenticated and granted access to vhost 'mirror'
    2021-02-06 06:05:19.384 [warning] <0.963.0> closing AMQP connection <0.963.0> (10.4.7.1:54778 -> 10.4.7.60:5672, vhost: 'mirror', user: 'admin'):
    client unexpectedly closed TCP connection
    

    1.2.4. Erlang虚拟机优化

    RabbitMQ实在Erlang虚拟机上运行的,Erlang虚拟机的配置对RabbitMQ有着较大的影响,设计进程调度、内存分配、垃圾回收、IO等。相关配置有三个环境变量

  • RABBITMQ_SERVER_ERL_ARGS Erlang的启动参数,会覆盖掉所有启动脚本中的默认配置,不推荐配置

  • RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS Erlang的附加启动参数,可以安全的替换默认值,一般都推荐该项
  • `RABBITMQ_CTL_ERL_ARGS`` CLI工具的配置

    1.2.4.1. CPU使用

    RabbitMQ CPU使用情况,可以通过 rabbitmq-diagnostics runtime_thread_stats 查看,指标含义: https://rabbitmq.com/runtime.html#thread-stats

  • Runtime Schedulers

调度程序数量配置,如果是RabbitMQ程序独占的机器,不需要配置,程序自动检测CPU核心数,并启动相同数量的调度程序。但是在容器环境或者共享的虚拟机上,需要显式配置调度器数量,采用 +S 参数。如启动四个调度程序,则使用: RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+S 4:4" 。如果对性能有要求,将RabbitMQ部署在独立的VM上,因为CPU资源争抢会导致RabbitMQ性能损耗很大。

  • Scheduler Busy Wating

默认情况下,当RabbitMQ工作线程空闲时,它会等待一段时间,如果还没有工作则进入休眠状态,休眠状态可以降低CPU使用率,但是当突然来了大量任务,唤醒工作线程需要一定的时间。一般不需要调整该参数,除非你的资源(如VM)是按照CPU负载进行计费的。降低等待时间 RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+sbwt very_short +sbwtdcpu very_short +sbwtdio very_short" ,设置为较短的等待时间,会降低CPU使用率,但是可能会造成更高的延迟。

  • Scheduler CPU Binding

CPU绑定,绑定后的性能可以更高,默认是不绑定。绑定策略:Erlang手册Rabbitmq手册

1.2.4.2. 内存分配

Runtime内存分配也是一个重要参数,不应该过早优化它,当RabbitMQ存在性能瓶颈再调整,而且调整需要配合监控信息进行调整,合理的配置可以减少内存碎片并提升性能。 RabbitMQ手册

1.2.4.3. 对等节点之间通信缓冲区大小

对等节点之间的缓冲区大小默认值为 128MB,绝大部分场景中这个值足够了,如果节点之间的流量非常大,则需要使用调整,调整的依据应该是缓冲区大小不够使用,在日志中会有相应标志 busy_dist_port
可以使用环境变量调整,单位KB: RABBITMQ_DISTRIBUTION_BUFFER_SIZE=192000
也可以使用参数调整,单位KB: RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+zdbbl 192000"

2019-04-06 22:48:19.031 [warning] <0.242.0> rabbit_sysmon_handler busy_dist_port <0.1401.0>

1.2.4.4. Erlang 线程数量

默认每个node上轻量级线程的数量为100万,绝大部分场景都够用了,如果并发特别高,可以适当增加:

RABBITMQ_MAX_NUMBER_OF_PROCESSES=2000000
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+P 2000000"

2. 监控

RabbitMQ的监控非常简单,在RabbitMQ 3.8自带了metrics接口插件,通过安装相关插件就可以获取prometheus规范的 /metrics 接口数据。
官方文档:https://www.rabbitmq.com/prometheus.html
具体操作如下:

在所有的rabbitmq接口启用 监控插件
rabbitmq-plugins enable rabbitmq_prometheus

metrics 接口数据刷新率配置项,建议改为 15s 或者30s,根据prometheus的数据采集周期来定
collect_statistics_interval = 5000 # 单位ms

从https://grafana.com/rabbitmq获取grafana模板
grafana需要安装插件 flant-statusmap-panel
[root@duduniao grafana]# ./bin/grafana-cli --pluginsDir data/plugins/ plugins install flant-statusmap-panel

image.png
image.png


3. 备份与恢复

RabbitMQ的数据分为两种:

  • 拓扑关系数据(也成为Definitions),包含了对象关系,比如用户、vhost、交换机、队列等等。通常备份的就是该数据
  • 消息数据(Message),队列的消息数据,这种数据必须要停机备份,否则备份的意义不大,因为大部分消息的生命周期很短 ```

    备份

    root@ubuntu-7-62:~# rabbitmqctl export_definitions /tmp/backup.json # 目标路径需要 rabbitmq 进程用户具备写入权限

    运行中导入

    root@ubuntu-7-60:~# rabbitmqctl import_definitions /tmp/backup.json

在启动rabbitmq后立即暂停服务

root@ubuntu-7-60:~# rabbitmqctl await_startup —timeout 300 # 等待五分钟 root@ubuntu-7-60:~# rabbitmqctl import_definitions /tmp/backup.json # 导入数据 ```