RabbitMQ提供了三种方式来定制化服务:
环境变量(Environment Variables)
。通过环境变量配置服务端参数,例如节点名称、RabbitMQ配置文件的地址、节点内部通信端口等配置文件(Configuration File)
。通过配置文件定义服务和插件设置,例如TCP监听端口、以及其他网络相关的设置、内存限制、磁盘限制等;运行时参数和策略(Runtime Parameters and Policies)
。通过运行时参数和策略定义集群层面的服务设置。
环境变量
RabbitMQ的环境变量都是以"RABBITMQ_"下划线开头,可以在Shell中设置,也可以在rabbitmq-env.conf文件中设置,如果在非shell环境中,需要去掉"RABBITMQ_"这个前缀。优先级为Shell环境最优先,conf文件次之,最后是默认的配置。
root@node01:~# find / -name rabbitmq-env.conf
/etc/rabbitmq/rabbitmq-env.conf
root@node01:~# cat /etc/rabbitmq/rabbitmq-env.conf
# Defaults to rabbit. This can be useful if you want to run more than one node
# per machine - RABBITMQ_NODENAME should be unique per erlang-node-and-machine
# combination. See the clustering on a single machine guide for details:
# http://www.rabbitmq.com/clustering.html#single-machine
#NODENAME=rabbit
# By default RabbitMQ will bind to all interfaces, on IPv4 and IPv6 if
# available. Set this if you only want to bind to one network interface or#
# address family.
#NODE_IP_ADDRESS=127.0.0.1
# Defaults to 5672.
#NODE_PORT=5672
# Default rabbitmq-server wait timeout.
RABBITMQ_STARTUP_TIMEOUT=600
注意:rabbitmq.conf和rabbitmq-env.conf文件位置
默认情况下,它们没有被创建。如果需要创建这些文件,请在以下指定位置创建:
- Generic UNIX - $RABBITMQ_HOME/etc/rabbitmq/
- Debian - /etc/rabbitmq/
- RPM - /etc/rabbitmq/
- Mac OSX (Homebrew) - ${install_prefix}/etc/rabbitmq/, the Homebrew prefix is usually /usr/local
- Windows - %APPDATA%\RabbitMQ\
如果rabbitmq-env.conf不存在,则可以在由RABBITMQ_CONF_ENV_FILE变量指定的位置手动创建。 在Windows系统上,它名为rabbitmq-env.bat。
如果rabbitmq.conf不存在,可以手动创建。 如果更改位置,请设置RABBITMQ_CONFIG_FILE环境变量。 RabbitMQ自动将.conf扩展名附加到此变量的值。
更改后重新启动服务器。 添加或删除配置文件后,Windows服务用户需要重新安装该服务。
当采用rabbitmq-server -detached启动RabbitMQ服务的时候,此服务节点默认以“rabbit@”加上当前的Shell环境的hostname(主机名)来命名,即rabbit@$HOSTNAME。例如:
root@node01:~# hostname
node01
root@node01:~# rabbitmq-server -detached
root@node01:~# rabbitmqctl cluster_status
Cluster status of node rabbit@node01 ...
Basics
Cluster name: rabbit@node01
Disk Nodes
rabbit@node01
Running Nodes
rabbit@node01
Versions
rabbit@node01: RabbitMQ 3.8.9 on Erlang 23.2.1
Maintenance status
Node: rabbit@node01, status: not under maintenance
......
如果需要指定节点的名称,而不是采用默认的方式,可以在rabbitmq-server命令前添加RABBITMQ_NODENAME变量来设定指定的名称。例如:
root@node01:~# RABBITMQ_NODENAME=rabbit@node02 rabbitmq-server -detached
总之,RabbitMQ环境变量名的前缀是RABBITMQ_。一个典型的变量RABBITMQ_var_name的设置如下:
- 如果定义了shell环境变量RABBITMQ_var_name,则RabbitMQ会使用该环境变量;(优先级最高)
- 否则,如果在rabbitmq-env.conf中设置了一个名为var_name的变量,则该变量会生效;(优先级次之)
- 否则,会使用系统的默认配置。(优先级最低)
下面是一些常见的RabbitMQ配置项:
- RABBITMQ_NODE_IP_ADDRESS:绑定某个特定的网络接口。默认为空字符串,即意味着绑定到所有网络接口上。如果想绑定到某个特定网络接口上,可修改此值。如果要绑定两个以上的接口,需要在rabbitmq.config中使用tcp_listeners key配置。
- RABBITMQ_NODE_PORT:监听客户端连接的端口号,默认为5672。
- RABBITMQ_DIST_PORT:RabbitMQ节点内部通信的端口号,默认为RABBITMQ_NODE_PORT + 20000,即25672。当在配置文件中设置了kernel.inet_dist_listen_min或kernel.inet_dist_listen_max时,此环境变量将被忽略。
- ERL_EPMD_ADDRESS:Interface(s) used by
epmd
, a component in inter-node and CLI tool communication. Default: all available interfaces, both IPv6 and IPv4. - ERL_EPMD_PORT:Port used by epmd, a component in inter-node and CLI tool communication. Default: 4369
- RABBITMQ_DISTRIBUTION_BUFFER_SIZE:用于节点间通信连接的
传出数据缓冲区大小限制
,以千字节为单位。 不建议使用低于64 MB的值。默认为:128000 - RABBITMQ_NODENAME:RabbitMQ的节点名称,默认为:Unix*: rabbit@$HOSTNAME;Windows:rabbit@%COMPUTERNAME%。在每个Erlang节点和机器的组合中,节点名称必须唯一。
- RABBITMQ_CONF_ENV_FILE:RabbitMQ环境变量的配置文件(rabbit-env.conf)的地址,默认为$RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf。注意与RabbitMQ配置文件rabbitmq.config的区别。
- RABBITMQ_ADVANCED_CONFIG_FILE:“高级”(基于Erlang术语)RabbitMQ配置文件路径,扩展名为.config。 例如,/data/rabbitmq/advanced.config。默认:Generic UNIX:$RABBITMQ_HOME/etc/rabbitmq/advanced.config;Debian:/etc/rabbitmq/advanced.config;RPM:/etc/rabbitmq/advanced.config,其他参见官方文档。
- RABBITMQ_USE_LONGNAME:如果当前的hostname为node1.longname,那么默认情况下创建的节点名称为rabbit@node1,将此参数设置为true时,创建的节点名称就为rabbit@node1.longname,即使用了长名称命名。默认值为空。
- RABBITMQ_MNESIA_BASE:RABBITMQ_MNESIA_DIR的父目录。除非明确设置了RABBITMQ_MNESIA_DIR目录,否则每个节点都应该配置这个环境变量。默认值为:Generic UNIX package: $RABBITMQ_HOME/var/lib/rabbitmq/mnesia,Ubuntu and Debian packages: /var/lib/rabbitmq/mnesia/,RPM: /var/lib/rabbitmq/plugins,Windows: %APPDATA%\RabbitMQ,其他参见官方文档。注意对于RabbitMQ的操作用户来说,需要有对当前目录可读、可写、可创建文件及子目录的权限。
- RABBITMQ_MNESIA_DIR:包含RabbitMQ服务节点的数据库、数据存储及集群状态等目录,默认值:Generic UNIX package: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME,Ubuntu and Debian packages: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME,RPM: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME,Windows: %APPDATA%\RabbitMQ$RABBITMQ_NODENAME。其他参见官方文档。
- RABBITMQ_PLUGINS_DIR:插件所在路径。默认值为Generic UNIX package: $RABBITMQ_HOME/plugins,Ubuntu and Debian packages: /var/lib/rabbitmq/plugins,RPM: /var/lib/rabbitmq/plugins,Windows: %RABBITMQ_HOME%\plugins,其他参见官方文档。
- RABBITMQ_PLUGINS_EXPAND_DIR:节点扩展插件(解压缩)的目录,并将其用作代码路径位置。 不得包含路径限制部分中提到的任何字符。默认为:Generic UNIX package: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME-plugins-expand,Ubuntu and Debian packages: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME-plugins-expand,RPM: $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME-plugins-expand,其他参见官方文档。
- RABBITMQ_SERVICENAME:安装服务的名称,这将显示在services.msc中,默认为RabbitMQ
- RABBITMQ_CONSOLE_LOG:设置此变量为new或reuse,可将服务器控制台输出重定向到名为%RABBITMQ_SERVICENAME%.debug 的文件中,该文件默认位于RABBITMQ_BASE目录下。如果没有设置, 服务器控制台输出将被丢弃(默认情况).
new:服务每次启动时都会创建一个新文件.
reuse:每次服务启动的时候,文件都会被覆盖. - RABBITMQ_SERVER_CODE_PATH:启动运行时,将指定额外的代码路径(目录)。 启动节点时将传递给erl命令。默认为空
- RABBITMQ_CTL_ERL_ARGS:调用rabbitmqctl时使用的erl命令的参数。 可以设置为指定用于Erlang分发的端口范围:
-kernel inet_dist_listen_min 35672
-kernel inet_dist_listen_max 35680
默认为空。 - RABBITMQ_SERVER_ERL_ARGS:调用RabbitMQ服务器时使用的erl命令的标准参数。 应该仅出于调试目的而将其覆盖。 覆盖此变量将替换默认值。默认为:Unix*: +P 1048576 +t 5000000 +stbt db +zdbbl 128000,Windows:None。
- RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:调用RabbitMQ服务器时使用的erl命令的附加参数。 此变量的值将附加到默认参数列表(RABBITMQ_SERVER_ERL_ARGS)。默认为空
- RABBITMQ_SERVER_START_ARGS:调用RabbitMQ服务器时使用的erl命令的附加参数。 这不会覆盖RABBITMQ_SERVER_ERL_ARGS。默认为空。
- RABBITMQ_SCHEMA_DIR:RabbitMQ保留新样式配置文件使用的配置架构的目录。
- RABBITMQ_LOG_BASE:RabbitMQ服务日志所在基础目录,默认为$RABBITMQ_HOME/var/log/rabbitmq
- RABBITMQ_LOGS:RabbitMQ服务于Erlang相关的日志,默认为:$RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME.log
实际生产中常用的配置示例如下:
#配置文件的地址
CONFIG_FILE=/apps/conf/rabbitmq/rabbitmq
#环境变量的配置文件的地址
CONF_ENV_FILE=/apps/conf/rabbitmq/rabbitmq-env.conf
#服务日志的地址
LOG_BASE=/apps/logs/rabbitmq
#Mnesia的路径
MNESIA_BASE=/apps/dbdat/rabbitmq/mnesia
配置文件
检查配置文件的地址的方法:
- 查看RabbitMQ服务启动时候打印的日志信息
- 如果看到not found字样,检查日志打印的路径中有没有相关的配置文件,或者检查配置文件的地址是否设置正确。如果rabbitmq.config不存在,可以手动创建它。
- 通过查看进程信息的方式检查配置文件的位置。通过
ps aux| grep rabbitmq
命令查看RabbitMQ进程的信息。如果rabbitmq.config文件不处于默认的路径中,则会有-config选项标记正在使用的路径。
配置项
配置文件Rabbitmq.conf允许配置RabbitMQ服务器和插件。 从RabbitMQ 3.7.0开始,格式为sysctl格式
。
syntax语法可以在3行中简要说明:
- 一种设置使用一行
- 行结构化key = value
- 以#字符开头的任何行都是注释
一个简单的示例配置文件如下:
# this is a comment
listeners.tcp.default = 5673
经典配置格式中的相同示例:
%% this is a comment
[
{rabbit, [
{tcp_listeners, [5673]}
]
}
].
RabbitMQ服务相关的配置项如下所示(直接看英文会更真实,官方地址为:https://www.rabbitmq.com/configure.html):
配置加密
配置文件中一些敏感的信息可以进行加密,RabbitMQ启动时会对这些信息进行解密。对这些项进行加密并不是意味着系统的安全性增强了,而是需要遵循一些必要的规范,将敏感数据不以文本的形式保存在配置文件中。
可以使用{encrypted,<<"加密后的字符串">>}
和{config_enter_decoder,[{passphrase,<<"口令">>}]}
来进行对应的加密和解密,加密后的字符串可以通过rabbitmqctl encode '<<“密码”>>'
口令来获得,解密则可以使用rabbitmqctl encode --decode '{encrypted,<<"加密后的字符串">>}'
口令来获取。
默认情况下,加密机制PBKDF2用来从口令中派生出密钥,默认的Hash算法是SHA512,当然这也是可配置的。
优化网络配置
网络是客户端和RabbitMQ之间通信的媒介,RabbitMQ支持的所有协议都是基于TCP层面的,除了操作系统内核参数和DNS,所有的RabbitMQ设置都可以通过在rabbitmq.config配置文件中配置实现。
默认情况下,RabbitMQ会在所有可用的网络接口上监听5672端口。优化网络配置的一个重要目标就是提高吞吐量,比如禁用Nagle算法、增大TPC缓冲区的大小。每个TOC连接都分配了缓冲区。一般来讲,缓冲区越大,吞吐量也会越高,但是每个连接上耗费的内存也就越多,从而使总体服务的内存增大,这是一个权衡的问题。
在Linux操作系统中,默认会自动调节TCP缓冲区的大小,通常会设置为80KB到120KB之间。要提高吞吐量可以使用rabbit.tcp_listeners_options来加配置。
Erlang在运行时使用线程池来异步执行I/O操作。线程池的大小可以通过RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS环境变量来调节,但这个值并不是越高就越能提高吞吐量。
在优化并发连接数的时候,需要确保系统有足够的文件句柄来支撑客户端和Broker的交互。可以用每个节点连接数乘以1.5来粗略的估算限制,增大句柄数会增加闲置内存的使用量
禁用Nagle算法可以提高吞吐量,但其主要作用还是用于减少延迟,RabbitMQ内部节点交互式可以在kernel.inet_default_connect_options和kernel.inet_default.tcp_listen_options配置项中配置{nodelay,true}来禁用Nagle算法,rabbitmq.tcp_listen_options中同样需要添加上述配置;
当连接数量过多时,需要确保服务器能够接受入站连接,未接受的TCP连接将会放在长度限制的队列中,可以通过rabbit.tcp_listen_options.backlog参数进行设置,默认值未128,当挂起的连接队列长度超出此值时,连接将被操作系统拒绝。
下面是通用的TCP套接字选项
rabbit.tcp_listen_options.nodelay
:当设置为true,可禁用Nagle算法。默认为true。高度推荐给大多数用户。
rabbit.tcp_listen_options.sndbuf
:参考先前讨论的TCP缓冲区,一般取值范围在88KB到128KB的范围。增大缓冲区可以提高消费者的吞吐量,同时也会加大每个连接上的内存使用量。减小则会有相反的效果。
rabbit.tcp_listen_options.recbuf
:参考先前讨论的TCP缓冲区. 默认值的效果类似于rabbit.tcp_listen_options.sndbuf,但这里一般针对的是发布者或协议操作。
rabbit.tcp_listen_options.backlog
:队列中未接受连接的最大数目。达到此值时,新连接会被拒绝。对于成千上万的并发连接环境以及可能存在大量客户重新连接的场景,可设为4096或更高.
rabbit.tcp_listen_options.linger
:当套接字关闭时,设置为{true, N},用于设置刷新未发送数据的超时时间,秒为单位
rabbit.tcp_listen_options.keepalive
:当设置为true时,将启用TCP keepalives。默认为false。对于连接长时间空闲(至少10分钟)的环境来说是有意义的,尽管更推荐使用heartbeats 选项。
与操作系统有关的设置可影响RabbitMQ的运行。注意这一类型的内核参数在/etc/sysctl.conf文件(Linux操作系统)中配置。以下是几个重要的可配置内核选项包括:
fs.file-max
:内核分配的最大文件句柄数。极限值和当前值可通过/proc/sys/fs/file-nr来查看。
net.ipv4.ip_local_port_range
:本地IP端口范围,定义为一对值。该范围必须为并发连接的峰值数提供足够的条目。
net.ipv4.tcp_tw_reuse
:当启用时,允许内核重用TIME_WAIT状态的sockets.参考Coping with the TCP TIME_WAIT connections on busy servers 来了解细节. 当用在NAT时,此选项是很危险的。
net.ipv4.tcp_fin_timeout
:降低此值到5-10 可减少连接关闭的时间,之后会停留在TIME_WAIT状态.建议用在有大量并发连接的场景.
net.core.somaxconn
:监听队列的大小(同一时间建立过程中有多少个连接)。默认是128。增大到4096或更高,可以支持入站连接的爆发,如clients集体重连。
net.ipv4.tcp_max_syn_backlog
:尚未收到连接客户端确认的连接请求的最大数量。默认为128,最大值为65535。优化吞吐量时,4096和8192是推荐的起始值。
net.ipv4.tcp_keepalive_*
:net.ipv4.tcp_keepalive_time, net.ipv4.tcp_keepalive_intvl,net.ipv4.tcp_keepalive_probes 用于配置TCP存活时间。AMQP 0-9-1 和 STOMP有Heartbeats ,这部分撤销了其效果,换句话说,它可以花几分钟来探测未响应的同等端,如:硬件或掉电故障. 当启用了TCP keepalive,我们建议设置心跳超时为8-20秒.
net.ipv4.conf.default.rp_filter
:启用反向地址过滤. 如果你的系统不关心IP地址欺骗 ,那么就禁用它.
参数及策略
RabbitMQ的绝大多数配置可以通过rabbitmq.config来完成,但是有些不适合在其中实现,比如某些配置项不需要同步到集群中的其他节点中,或者某项配置需要在运行时更改(我们称其为parameter),因为rabbitmq.config需要重启broker才能生效。这种类型的配置在RabbitMQ中的另一种称呼为参数(Parameter),也可以称为运行时参数。
Parameter可以通过rabbitmqctl或RabbitMQ Management插件提供的HTTP API接口来设置。RabbitMQ中一共有两种类型的parameter:vhost级别、global级别。其中vhost级别的Parameter由一个组件名称(component name)、名称(name)和值(value)组成,而global级别的参数由一个名称和值组成。其所对应的值都是JSON类型的。
vhost级别的参数对应的rabbitmqctl相关的命令有:set_parameter、list_parameters和clear_parameter。与rabbitmqctl工具对应的HTTP API接口如下所述:
- 设置一个参数:PUT /api/parameters/{component_name}/vhost/name
- 清除一个参数:DELETE /api/parameters/{component_name}/vhost/name
- 列出指定vhost中的所有参数:GET /api/parameters
globale级别的Parameter的set、clear和list功能所对应的rabbitmqctl工具与HTTP API接口如下:
1. rabbitmqctl:
- rabbitmqctl set_global_parameter name value
- rabbitmqctl list_global_parameters
- rabbitmqctl clear_global_parameter name
2. HTTP API接口 - PUT /api/global-parameters/name
- DELETE /api/global-parameters/name
- GET /api/global-parameters/
除了一些固定的参数,客户端在创建交换器或者队列的时候可以配置一些可选的属性参数来获得一些不同的功能,比如x-message-ttl、x-expires、x-max-length等。通过客户端设置的这些属性参数,一旦设置成功就不能再改变,除非删除原来的交换器或队列之后再重新创建。
Policy是一种特殊的Parameter用法,它是vhost级别的,一个Policy可以配置一个或多个队列以便于批量管理,此外Policy支持动态地修改一些属性参数,如Federation、镜像、备份交换器、死信等功能,大大提高了应用的灵活度。rabbitmq_managemet插件提供了对Policy的支持,可以在“Admin”->“Poicies”->"Add/update a ploicy"中添加一个Policy,参数如下:
- Virtual host:表示当前Policy所在的vhost
- Name:表示当前Policy的名称
- Pattern:表示一个正则表达式,用来匹配相关的队列或者交换器
- Apply to:用来指定Policy作用于哪一方;
- Priority:表示优先级,如果多个Policy作用于同一个交换器或者队列,那么Priority最大的那个Policy才会有用;
- Definition:定义一组或多组键值对,为匹配的交换器或队列附加相关的功能
Policy作为一种Parameter,同样可以使用rabbitmqctl工具或者HTTPAPI接口来操作:
rabbitmqctl set_policy [-p vhost] [--priority] [--apply-to apply-to] {name} {pattern} {definition}
其中参数name、patten和definition是必填项。
如果两个或多个Policy都作用于同一个交换器或者队列上,且优先级一样,那么参数最多的Policy拥有决定权,如果参数一样多,后添加的Policy具有决定权。
参考资料
- RabbitMQ官方配置文档:https://www.rabbitmq.com/configure.html#customise-environment
- 《RabbitMQ实战指南》 朱忠华 著
- https://www.cnblogs.com/Jscroop/p/14290303.html#_label7_0
- https://blog.youkuaiyun.com/qq_33730729/article/details/83899756