RabbitMQ(五)配置

RabbitMQ(五)配置

一. 概述

一般情况下,只需要使用默认的内建配置来运行 RabbitMQ,也可以利用调节系统范围内的参数来达到定制化的需求。

RabbitMQ 提供了三种方式来定制化服务:

  1. 环境变量(Enviroment Variables):RabbitMQ 服务端参数可以通过环境变量进行配置,例如:节点名称、 RabbitMQ 配直文件的地址、节点内部通信端口等。
  2. 配置文件( Configuration File):可以定义 RabbitMQ 服务和插件设置,例如:TCP 听端口,以及其他网络相关的设直、内存限制、磁盘限制等。
  3. 运行时参数和策略( Runtime Parameters and Policies):可以在运行时定义集群层面的服务设置。

二. 环境变量

2.1 配置方式

RabbitMQ 的环境变量都是以 RABBITMQ_ 开头的,可以在 Shell 环境中设置,也可以在 rabbitmq-env.conf 这个 RabbitMQ 环境变量的定义文件中设置。在非 Shell 环境中配置,则需要将 RABBITMQ_ 这个前缀去除。

指令 rabbitmq-server -detached 启动 RabbitMQ 服务的时候,此服务节点默认以 rabbit@ 加上当前的 Shell 环境的 hostname(主机名)来命名,即 rabbit@$HOSTNAME 。可以在 rabbitmq-server 命令前添 RABBITMQ_NODENAME 变量来设定指定的名称。

1
2
$ RABBITMQ_NODENAME=rabbit@node2 rabbitmq-server -detached
Warning: PIO file not written; -detached was passed.

优先级顺序:Shell环境 > rabbitmq-env.conf 配置文件 > 默认配置。

配置 rabbitmq-env.conf

1
2
3
4
5
6
7
8
# RabbitMQ 环境变量的定义文件
# 定义节点名称
NODENAME=rabbit@node1
# 定义 RabbitMQ 的对外通信端口号
NODE_PORT=5672
# 定义 RabbitMQ 配置文件的目录,注意对于 rabbitmq.config
# 文件来说这里不用添加".config后缀"
CONFIG_FILE=/opt/rabbitmq/etc/rabbitmq/rabbitmq

默认配置记录在 $RABBITMQ HOME/sbin/rabbitmq-defaults 文件。

2.2 常见的RabbitMQ变量

变量名称 描述
RABBITMQ_NODE_IP_ADDRESS 绑定某个特定的网络接口。默认值是空字符串,即绑定到所有网络接口上。如果要绑定两个或者更多的网络接口,可以参考 rabbitmq.config 中的 tcp_listeners 配置
RABBITMQ_NODE_PORT 监听客户端连接的端口号,默认为 5672
RABBITMQ_DIST_PORT RabbitMQ 节点内部通信的端口号,默认值为 RABBITMQ_NODE_PORT+20000, 即25672。如果设置了 kernel.inet_dist_listen_min 或者 kemel.inect_dist_listen_max
RABBITMQ_NODENAME RabbitMQ 的节点名称,默认为 rabbit@$HOSTNAME 。在每个 Erlang 节点和机器的组合中,节点名称必须唯一
RABBITMQ_CONF_ENV_FILE RabbitMQ 环境变量的配置文件(rabbitmq-env.conf)的地址,默认值为 $RABBITMQ_HOME/etc/rabbitmq/rabbi tmq-env.conf 注意这里与 RabbitMQ 配置文件 rabbitmq.config 的区别
RABBITMQ_USE_LONGNAME 如果当前的 hostname 为 node1.longname ,那么默认情况下创建的节点名称为 rabbit@node1 ,将此参数设置为 true 时,创建的节点名称就为 rabbit@node1.longname,即使用了长名称命名,默认值为空
RABBITMQ_CONFIG_FILE RabbitMQ 配置文件(rabbitmq.config)的路径,注意没有“.config”的后缀.默认值为 $RABBITMQ_HOME/etc/rabbitmq/rabbitmq
RABBITMQ_MNESIA_BASE RABBITMQ_MNESIA_DIR 的父目录。除非明确设置了 RABBITMQ_MNESIA _DIR 目录,否则每个节点都应该配置这个环境变量。默认值为 $RABBITMQ_HOME/var/lib/rabbitmq/mnesia 注意对于 RabbitMQ 的操作用户来说,需要有对当前目录可读、可写、可创建文件及子目录的权限
RABBITMQ_MNESA_DIR 包含 RabbitMQ 服务节点的数据库、数据存储及集群状态等目录,默认值为 $RABBITMQ_MNESIA_BASE/$RABBITMQ_NODENAME
RABBITMQ_LOG_BASE RabbitMQ 服务日志所在基础目录.默认值为$RABBITMQ_HOME/var/log/rabbitmq
RABBITMQ_LOGS RabbitMQ 服务与 Erlang 相关的日志,默认值为 $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME.log
RABBITMQ_SASL_LOGS RabbitMQ 服务于 Erlang 的 SASL(System Application Support Libraries)相关的日志,默认值为 $RABBITMQ_LOG_BASE/$RABBITMQ_NODENAME-sasl.log
RABBITMQ_PLUGINS_DIR 插件所在路径。默认值为$RABBITMQ_HOME/plugins

一般不建议修改环境变量,如果生产环境有特殊要求,可以参考:

1
2
3
4
5
6
7
8
# 配置文件的地址
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 服务的时候会打印相关信息,可以检查服务日志来判断配置文件地址。

配置失效的情况:

1
config file(s) : /opt/rabbitmq/sbin/../etc/rabbitmq/rabbitmq. config(not found)

检查对应路径下是否有相关配置文件,以及配置文件地址是否设置正确(通过 RABBITMQ_CONFIG_FILE 变量或者 rabbitmq-env.conf 文件设置)。

还可以通过查看进程信息的方式来检查配直文件的位置。通过 ps aux|grep rabbitmq 命令查看到 RabbitMQ 进程的信息,如果 rabbitmq.config 文件不处于默认的路径中,则会有 -config 选项标记正在使用的路径。

3.1 配置项

极简的 rabbitmq.config 文件:

1
2
3
4
5
6
7
[
{
rabbit, [
{tcp_listeners, [5673]}
]
}
].

上面的配置将 RabbitMQ 监听 AMQP 0-9-1 客户端连接的默认端口号从 5672 修改为 5673。

RabbitMQ 服务相关配置表格暂略。

3.2 配置加密

配置文件中有些敏感的配置项可以被加密,在 RabbitMQ 启动时可以对这些项进行解密。在配置文件中将加密之后的值以 {encrypted, 加密的值} 形式包裹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
{
rabbit, [
{default_user,<<"guest">>},
{default_pass,
{
{encrypted,<<"HuVPYgSUdbogWL+2jGsgDMGZpDfiz+HurDuedpG8dQX/U+DMHcBluA15a5jRnAbs+OviX5EmsJJ+c0XgRRcADA==">>}
}
},
{loopback_users,[]},
{config_entry_decoder,[
{passphrase,<<"zzhpassphrase">>}
]}
]
}
].

config_entry_decoder 项中的 passphrase 配置的就是口令。注意这里将 loopback_users 项配置为 [] ,就可以使用非本地网络访问 RabbitMQ 了,如果开启了 RabbitMQ Management 插件,就可以使用 guest/guest 的用户及密码来访问 Web 管理界面了。

passphrase 内容可以以单独的文件来赋值:

1
2
3
{config_entry_decoder,[
{passphrase,"/path/to/passphrase/file"}
]}

加密解密:

1
2
3
$ rabbitmqctl encode <<"guest">> zzhpassphrase 
{encrypted,<<"HuVPYgSUdbogWL+2jGsgDMGZpDfiz+HurDuedpG8dQX/U+DMHcBluA15a5jRnAbs+OviX5EmsJJ+c0XgRRcADA==">>}
$ rabbitmqctl encode --DECODE <<"guest">> '{encrypted,<<"HuVPYgSUdbogWL+2jGsgDMGZpDfiz+HurDuedpG8dQX/U+DMHcBluA15a5jRnAbs+OviX5EmsJJ+c0XgRRcADA==">>}' zzhpassphrase

默认情况下,加密机制 PBKDF2 用来从口令中派生出密钥。默认的 Hash 算法是 SHA512,默认的迭代次数是 1000 ,以及默认的加密算法为 AES_256_CBC。可以在配置文件中进行修改:

1
2
3
4
5
6
{config_entry_decoder,[
{passphrase,"zzhpassphrase"},
{cipher, blowfish_cfb64},
{hash, sha256},
{iterations, 10000}
]}

或者通过 rabbitmqctl encode 命令设置:

1
$ rabbitmqctl encode --cipher blowfish_cfb64 --hash sha256 --iterations 10000 '<<"guest">>' zzhpassphrase

3.3 优化网络配置

RabbitMQ 支持的所有协议都是基于 TCP 层面的,除了操作系统内核参数和 DNS,所有的 RabbitMQ 设置都可以通过在 rabbitmq.config 配置文件中配置来实现。

3.3.1 监听端口

RabbitMQ 在等待接收客户端连接时需要绑定一个或者多个网络接口(可以理解成IP地址),井监听特定的端口。网络接口使用 rabbit.tcp_listeners 选项来配置。默认情况下,RabbitMQ 会在所有可用的网络接口上监听 5672 端口。

1
2
3
4
5
6
7
8
9
10
[
{
rabbit, [
# 在一个指定的地址和端口上进行监听,同时在 IPv41Pv6 上监听
{tcp_listeners, [{"192.168.0.2", 5672},
{"::1", 5672}]}

]
}
].

3.3.2 提高吞吐量

优化网络配置的一个重要目标就是提高吞吐量,比如禁用 Nagle 算法、增大 TCP 缓冲区的大小。每个 TCP 连接都分配了缓冲区。一般来说,缓冲区越大,吞吐量也会越高,但是每个连接上耗费的内存也就越多,从而使总体服务的内存增大,这是一个权衡的问题。在 Linux 操作系统中,默认会自动调节 TCP 缓冲区的大小,通常会设置为 80KB 到 120KB 之间。

要提高吞吐量可以使用 rabbit.tcp_listen_options 来加大配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
[
{
rabbit, [
{tcp_listen_options, [
{backlog, 128},
{nodelay, true},
{linger, {true,0}},
{exit_on_close, false},
{sndbuf, 196608},
{recbuf, 196608}]}
]
}
].

大部分操作系统都限制了同一时间可以打开的文件句柄数。在优化并发连接数的时候,需要确保系统有足够的文件句柄数来支撑客户端和 Broker 的交互。可以用每个节点上连接的数目乘以1.5来粗略的估算限制。例如,要支撑 10 万个 TCP 连接,需要设置文件句柄数为 15 万。当 然,略微增加文件句柄数可以增加闲置机器内存的使用量,但这需要合理权衡。

如上所述,增大 TCP 缓冲区的大小可以提高吞吐量,如果减小 TCP 缓冲区的大小,这样 就可以减小每个连接上的内存使用量。如果并发量比吞吐量更重要,可以修改此值。

禁用 Nagle 算法可以提高吞吐量,但是其主要还是用于减少延迟。RabbitMQ 内部节点交互时可以在 kernel.inet_default_connect_options 和 kernel.inet_default_listen_options 配置项中配置 {nodelay, true} 来禁用 Nagle 算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[
{
kernel, [
{inet_default_connect_options, [{nodelay, true}]},
{inet_default_listen_options, [{nodelay, true}]}
]
},
{
rabbit, [
{tcp_listen_options, [
{backlog, 4096},
{nodelay, true},
{linger, {true,0}},
{exit_on_close, false}]}
]
}
].

3.3.3 设置线程池大小

Erlang 在运行时使用线程池来异步执行 IO 操作。线程池的大小可以通过 RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS 这个环境变量来调节。

1
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+A 128"

当机器的内核个数大于等于8时,建议将此值设置为大于等于 96 ,这样可以确保每个内核上可以运行大于等于 12 个 I/O 线程。

3.3.4 连接量大

当只有少量的客户端时,新建立的连接分布是非常不均匀的,但是由于数量足够小,所以没有太大的差异。当连接数量到达数万或者更多时,重要的是确保服务器能够接受入站连接。未接受的 TCP 连接将会放在有长度限制的队列中。这个通过 rabbit.tcp_listen_options.backlog 参数来设置,默认值为 128 ,当挂起的连接队列的长度超过此值时,连接将被操作系统拒绝。

3.3.5 一些可配置的内核选项

与操作系统有关的网络设置也会影响到 RabbitMQ 的运行,注意这一类型的内核参数在 /etc/sysctl.conf 文件(Linux 操作系统)中配置,而不是 rabbitmq.config 这个文件中。

四. 参数及策略

有些配置不太适合在 rabbitmq.config 中实现,比如某项配置不需要同步到集群中的其他节点中,或者某项配置需要在运行时更改,因为 rabbitmq.config 需要重启 Broker 才能生效。 这种类型的配置在 RabbitMQ 中的另一种称呼为参数( Paramter),也可以称之为运行时参数(Runtime Parameter)。

Parameter的设置方式:

  • 通过 rabbitmqctl 工具;
  • 通过 RabbitMQ Management 插件提供的 HTTP API 接口来设置。

RabbitMQ 一共有两种类型的 Parameter::

  • vhost 级别的 Parameter ,由一个组件名称(component name)、名称(name)和值 (value)组成。
  • global 级别的 Parameter ,由一个名称和值组成。

不管什么类型,值都是JSON类型的。例如 Federation upstream 是一个 vhost 级别的 Parameter ,它用来定义 Federation link 的上游信息,其对应的 Parameter 的组件名称为 “federation-upstream” ,名称对应于其自身的名称,而值对应于与上游的相关的连接参数等;对 Shovel 而言也可以通过 Parameter 设置,其对应组件名称为 “shovel”。

4.1 vhost级别Parameter

vhost 级别的参数对应的 rabbitmqctl 相关的命令有3种:

  • set_parameter:用来设置一个参数。

    1
    2
    3
    4
    5
    6
    7
    8
    $ rabbitmqctl set_parameter [-p vhost] {component_name} {name} {value} 
    # 示例
    $ rabbitmq-plugins enable rabbitmq_federation
    The following plugins have been enabled:
    rabbitmq_federation
    Applying plugin configuration to rabbit@node1... started 1 plugin.
    $ rabbitmqctl set_parameter federation-upstream f1 '{"uri":"amqp://root:root123@192.168.0.2:5672","ack-mode":"on-confirm"}'
    Setting runtime parameter "f1" for component "federation-upstream" to "{\"uri\":\"amqp://root:root123@192.168.0.2:5672\",\"ack-mode\":\"on-confirm\"}"
  • list_parameters:用来列出指定虚拟主机上所有的Parameter。

    1
    2
    3
    4
    5
    $ rabbitmqctl list_parameters [-p vhost] 
    # 示例
    $ rabbitmqctl list_parameters -p /
    Listing runtime parameters
    federation-upstream f1 {"uri":"amqp://root:root123@192.168.0.2:5672","ack-mode":"on-confirm"}
  • clear_parameter:用来清除指定的参数。

    1
    2
    3
    4
    5
    6
    $ rabbitmqctl clear_parameter [-p vhost] {componenet_name} {key} 
    # 示例
    $ rabbitmqctl clear_parameter -p / federation-upstream f1
    Clearing runtime parameter "fl" for component "federation-upstream"
    $ rabbitmqctl list_parameters -p /
    Listing runtime parameters

HTTP API接口:

  • 设置一个参数:PUT /api/parameters/{componenet_name}/vhost/name
  • 清除一个参数:DELETE /api/parameters/{componenet_name}/vhost/name
  • 列出指定 vhost 中的所有参数:GET /api/parameters

4.2 global级别Parameter

global 级别的 Parameter 的操作:

方式 详细内容
rabbitmqctl rabbitmqctl set_global_parameter name value
rabbitmqctl list_global_parameters
rabbitmqctl clear_global_parameter name
HTTP API接口 PUT /api/global-parameters/name
DELETE /api/global-parameters/name
GET /api/global-parameters/

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ rabbitmqctl list global parameters
Listing global runtime parameters
cluster_name "rabbit@node1"
$ rabbitmqctl set_global_parameter name1 '{}'
Setting global runtime parameter "name1" to "{}"
$ rabbitmqctl list_global_parameters
Listing global runtime parameters
cluster_name "rabbit@node1"
name1 []
$ rabbitmqctl clear_global_parameter name1
Clearing global runtime parameter "name1"
$ rabbitmqctl list_global_parameters
Listing global runtime parameters
cluster_name "rabbit@node1"

4.3 Policy

除了一些固定参数( 比如 durable 或者 exclusive),客户端在创建交换器或者队列的时候可以配置一些可选参数来获得一些不同的功能,比如 x-message-ttl 或 x-expires 或 x-max-length 等。通过客户端设定的这些属性参数一旦设置成功就不能再改变(不能修改也不能添加),除非删除原来的交换器或队列之后再重新创建新的。

Policy 的介入就可以很好的解决这类问题,是一种特殊的Parameter的用法。

  • Policy 是 vhost 级别的,一个 Policy 可以匹配多个队列或交换器,便于批量管理。
  • Policy 也支持动态的修改一些属性参数,提高了应用的灵活度。
  • 一般用来配置Federation、镜像、备份交换器、死信等功能。

rabbitmq_managemet 本身就提供了 Policy 的支持。可以在 【Admin】->【Policies】-> 【Add / update a policy】中添加一个 Policy 。

参数:

  • Virtual host :表示当前 Policy 所在的 vhost 是哪个。
  • Name :表示当前 Policy 的名称。
  • Pattern :一个正则表达式,用来匹配相关的队列或者交换器。
  • Apply to :用来指定当前 Policy 作用于哪一方。 共有三个选项:
    • Exchanges and queues:表示作用与 Pattern 所匹配的所有队列和交换器;
    • Exchanges:表示作用于 Pattern 所匹配的所有交换器;
    • Queues:表示作用于与 Pattern 所匹配的所有队列。
  • Priority :定义优先级,如果有多个 Policy 作用于同一个交换器或者队列,那么 Priority 最大的那个 Policy 才会有用 。
  • Definition :定义一组或者多组键值对,为匹配的交换器或者队列附加相应的功能。

作为一种 Paramter, Policy 也可以通过 rabbitmqctl 工具或者 HTTP API 接口来操 。与前面所讲的 Parameter 对应, rabbitmqctl 工具或者 HTTP API 接口各种都有 set、clear、list 的功能。

  • 用来设置一个 Policy:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ rabbitmqctl set_policy [-p vhost] [--priority priority] [--apply-to apply-to] {name} {pattern} {definition}
    # 示例,设置默认的 vhost 中所有以"^amq."开头的交换器为联邦交换器
    $ rabbitmqctl set_policy --apply-to exchanges --priority 1 p1 "^amq." '{"federation-upstream":"f1"}'
    Setting policy
    # HTTP API
    $ curl -i -u root:root123 -XPUT -d '{"pattern":"^amq\.","definition":{"federation-upstream":"f1"},"priority":1,"apply-to":"exchanges"}' http://192.168.0.2:15672/api/policies/%2F/p1
    HTTP/1.1 204 No Content
    server: Cowboy
    date: Mon, 21 Aug 2017 12:36:20 GMT
    content-length: 0
    content-type : application/json
    vary: accept, accept-encoding, origin
  • 列出默认 vhost 所有的 Policy :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ rabbitmqctl list_policies [-p vhost] 
    # 示例
    $ rabbitmqctl list_policies
    Listing policies
    / p1 exchanges ^amq. {"federation-upstream":"f1"}1
    # HTTP API
    $ curl -i -u root:rootl23 -XGET http://192.168.0.2:15672/api/policies/%2F
    HTTP/1.1 200 OK
    server: Cowboy
    date: Mon, 21 Aug 2017 12:37:30 GMT
    content-length: 125
    content-type: application/json
    vary: accept, accept-encoding, origin
    Cache-Control: no-cache
    [{"vhost":"/","name":"pl","pattern":"^amq\\.","apply-to":"exchanges","definition":{"federation-upstream":"f1"},"priority":1}]
  • 清除指定的 Policy :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ rabbitmqctl clear_policy [-p vhost] {name} 
    # 示例
    $ rabbitmqctl clear_policy p1
    Clearing policy "p1"
    # HTTP API
    $ curl -i -u root:rootl23 -XDELETE http://192.168.0.2:15672/api/policies/%2F/p1

    HTTP/1.1 204 No Content
    server: Cowboy
    date: Mon, 21 Aug 2017 12:38:55 GMT
    content-length: 0
    content-type: application/json
    vary: accept, accept-encoding, origin

    如果两个或多个 Policy 都作用到同一个交换器或者队列上,且这些 Policy 的优先级都是一样的,则参数项最多的 Policy 具有决定权。如果参数一样多,则最后添加的 Policy 具有决定权。


参考:

🔗 《RabbitMQ实战指南》