什么是动态 Broker 参数配置?
在 Kafka 安装目录的 config 路径下,有个 server.properties 文件。如果要设置 Broker 端的任何参数,我们必须在这个文件中显式地增加一行对应的配置,之后启动 Broker 进程,令参数生效。当后面需要变更任何参数时,我们必须重启 Broker。
社区于 1.1.0 版本中正式引入了动态 Broker 参数(Dynamic Broker Configs)。所谓动态,就是指修改参数值后,无需重启 Broker 就能立即生效,而之前在 server.properties 中配置的参数则称为静态参数(Static Configs)。显然,动态调整参数值而无需重启服务,是非常实用的功能。如果你想体验动态 Broker 参数的话,那就赶快升级到 1.1 版本吧。
Dynamic Update Mode
- read-only。被标记为 read-only 的参数和原来的参数行为一样,只有重启 Broker,才能令修改生效。
- per-broker。被标记为 per-broker 的参数属于动态参数,修改它之后,只会在对应的 Broker 上生效。
- cluster-wide。被标记为 cluster-wide 的参数也属于动态参数,修改它之后,会在整个集群范围内生效,也就是说,对所有 Broker 都生效。你也可以为具体的 Broker 修改 cluster-wide 参数。
per-broker 和 cluster-wide 的区别:Broker 端参数 listeners 想必你应该不陌生吧。它是一个 per-broker 参数,这表示你只能为单个 Broker 动态调整 listeners,而不能直接调整一批 Broker 的 listeners。
使用场景
- 动态调整 Broker 端各种线程池大小,实时应对突发流量。
- 动态调整 Broker 端连接信息或安全配置信息。
- 动态更新 SSL Keystore 有效期。
- 动态调整 Broker 端 Compact 操作性能。
- 实时变更 JMX 指标收集器 (JMX Metrics Reporter)。
如何保存?
- 首先,Kafka 将动态 Broker 参数保存在 ZooKeeper 中,具体的 znode 路径如下图所示。
- changes 是用来实时监测动态参数变更的,不会保存参数值
- topics 是用来保存 Kafka 主题级别参数的。虽然它们不属于动态 Broker 端参数,但其实它们也是能够动态变更的。
- users 和 clients 则是用于动态调整客户端配额(Quota)的 znode 节点。所谓配额,是指 Kafka 运维人员限制连入集群的客户端的吞吐量或者是限定它们使用的 CPU 资源。
- /config/brokers znode 才是真正保存动态 Broker 参数的地方
该 znode 下有两大类子节点。第一类子节点就只有一个,它有个固定的名字叫 < default >,保存的是前面说过的 cluster-wide 范围的动态参数;另一类则以 broker.id 为名,保存的是特定 Broker 的 per-broker 范围参数。由于是 per-broker 范围,因此这类子节点可能存在多个。
如果你仔细查看上图中的 ephemeralOwner 字段,你会发现它们的值都是 0x0。这表示这些 znode 都是持久化节点,它们将一直存在。即使 ZooKeeper 集群重启,这些数据也不会丢失,这样就能保证这些动态参数的值会一直生效。
如何配置?
目前,设置动态参数的工具行命令只有一个,那就是 Kafka 自带的 kafka-configs 脚本。
cluster-wide
下面这条命令展示了如何在集群层面设置全局值,即设置 cluster-wide 范围值。
1 2 | $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-default --alter --add-config unclean.leader.election.enable=true Completed updating default config for brokers in the cluster, |
如果要设置 cluster-wide 范围的动态参数,需要显式指定 entity-default。现在,我们使用下面的命令来查看一下刚才的配置是否成功。
1 2 3 | $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-default --describe Default config for brokers in the cluster are: unclean.leader.election.enable=true sensitive=false synonyms={DYNAMIC_DEFAULT_BROKER_CONFIG:unclean.leader.election.enable=true} |
从输出来看,我们成功地在全局层面上设置该参数值为 true。注意 sensitive=false 的字眼,它表明我们要调整的参数不是敏感数据。如果我们调整的是类似于密码这样的参数时,该字段就会为 true,表示这属于敏感数据。
per-broker
演示下如何设置 per-broker 范围参数。我们还是以 unclean.leader.election.enable 参数为例,我现在为 ID 为 1 的 Broker 设置一个不同的值。
1 2 | $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-name 1 --alter --add-config unclean.leader.election.enable=false Completed updating config for broker: 1. |
来查看一下刚刚的设置是否生效了
1 2 3 | $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-name 1 --describe Configs for broker 1 are: unclean.leader.election.enable=false sensitive=false synonyms={DYNAMIC_BROKER_CONFIG:unclean.leader.election.enable=false, DYNAMIC_DEFAULT_BROKER_CONFIG:unclean.leader.election.enable=true, DEFAULT_CONFIG:unclean.leader.election.enable=false} |
- 在 Broker 1 层面上,该参数被设置成了 false,这表明命令运行成功了。
- 从倒数第二行可以看出,在全局层面上,该参数值依然是 true。这表明,我们之前设置的 cluster-wide 范围参数值依然有效。
删除动态参数
删除动态参数要指定 delete-config
1 2 3 4 5 6 7 8 | # 删除cluster-wide范围参数 $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-default --alter --delete-config unclean.leader.election.enable Completed updating default config for brokers in the cluster, # 删除per-broker范围参数 $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-name 1 --alter --delete-config unclean.leader.election.enable Completed updating config for broker: 1. |
当我们删除完动态参数配置后,再次运行查看命令,结果如下:
1 2 3 4 5 6 7 8 | # 查看cluster-wide范围参数 $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-default --describe Default config for brokers in the cluster are: # 查看Broker 1上的动态参数配置 $ bin/kafka-configs.sh --bootstrap-server kafka-host:port --entity-type brokers --entity-name 1 --describe Configs for broker 1 are: |
重要的动态参数
log.retention.ms
修改日志留存时间应该算是一个比较高频的操作,毕竟,我们不可能完美地预估所有业务的消息留存时长。虽然该参数有对应的主题级别参数可以设置,但拥有在全局层面上动态变更的能力,依然是一个很好的功能亮点。
- num.io.threads 和 num.network.threads。
这是我们在前面提到的两组线程池。就我个人而言,我觉得这是动态 Broker 参数最实用的场景了。毕竟,在实际生产环境中,Broker 端请求处理能力经常要按需扩容。如果没有动态 Broker 参数,我们是无法做到这一点的。3. 与 SSL 相关的参数。
- 与 SSL 相关的参数
主要是 4 个参数(ssl.keystore.type、ssl.keystore.location、ssl.keystore.password 和 ssl.key.password)。允许动态实时调整它们之后,我们就能创建那些过期时间很短的 SSL 证书。每当我们调整时,Kafka 底层会重新配置 Socket 连接通道并更新 Keystore。新的连接会使用新的 Keystore,阶段性地调整这组参数,有利于增加安全性。
- num.replica.fetchers
这也是我认为的最实用的动态 Broker 参数之一。Follower 副本拉取速度慢,在线上 Kafka 环境中一直是一个老大难的问题。针对这个问题,常见的做法是增加该参数值,确保有充足的线程可以执行 Follower 副本向 Leader 副本的拉取。现在有了动态参数,你不需要再重启 Broker,就能立即在 Follower 端生效,因此我说这是很实用的应用场景。