总 第19篇

2019年 第15篇

一、问题导读Apache Kafka在全球各个领域各大公司获得广泛使用,得益于它强大的功能和不断完善的生态。其中Kafka动态配置是一个比较高频好用的功能,下面我们就来一探究竟。

  • 动态配置是如何设计的?
  • 动态配置优先级是怎样的?
  • Broker初始化是如何读取配置的?
  • 动态配置支持哪些特性功能?
  • 动态配置如何使用呢?

二、前言介绍

Kafka初始开源的几个版本,当broker初始化启动时,所有配置信息只能从server.properties静态文件读取,以后不再发生任何更改,随着Kafka逐步迭代,在线业务对稳定性和个性化要求越来越突出,需要能支持在线修改功能动态生效的需求应运而生。例如:按照topic维度清理数据,依据clientid限流,根据用户名称进行访问权限控制等等。目前Kafka最新版本支持以下几类动态配置。

三、发展历程

特性

版本

可配置字段

备注

增加topic级别配置特性支持 0.8.1

以下属性列表,后续迭代不断丰富topic.log.file.sizetopic.log.retention.hourstopic.log.retention.size......

对log的修改
增加client级别配置特性支持 0.9.0.0

producer_byte_rateconsumer_byte_rate.....

每秒生产/消费的byte数目大小
增加user级别配置特性支持 0.10.1.0

用户访问权限管理和资源控制

users + clients 组合粒度配置

增加broker级别配置特性支持 0.10.1.0

以下属性列表,后续迭代不断丰富leader.replication.throttled.ratefollower.replication.throttled.rate......

对broker有效

动态配置文件发展历程:

kafka在0.8.0对topic的管理功能分布在三个shell中,它们分别是kafka-list-topic.sh、kafka-create-topic.sh、kafka-delete-topic.sh、kafka-add-partitions.sh,后来社区考虑到topic管理功能过于分散,到了0.8.1版本有关topic所有功能收敛到kafka-topics.sh中。0.8.0中只有topic的创建、删除和列表及添加分区功能,到了0.8.1开始支持topics动态配置了。

0.9.0.0开始支持client(producer和consumer)客户端配额限流支持,确保不因为某个或少数几个topic的客户端占满了broker带宽资源和磁盘IO资源,影响其他客户端的正常读写,导致集群内主从同步也受到影响。这个功能对确保系统SLA大有好处,通过服务降级,保证写/生产不受影响,降低或暂停读/消费流量更容易解决系统资源瓶颈。

0.9.0版本动态配置与topic管理分离,为了保持向下兼容kafka-topics.sh依然包含操作topic动态配置功能,新增kafka-configs.sh支持clients和topics动态配置功能,所以kafka-topics.sh和kafka-configs.sh任意一个都可以修改topic动态配置

0.10.1.0版本新增支持users和brokers动态配置功能,user动态配置用于访问资源的权限控制,提升集群的访问和数据安全性,例如:用户对读/写/创建/删除等操作和API、topic、group资源访问控制。broker动态配置,在不用重启及影响服务运行情况下,broker级别功能实现动态生效,例如:副本注册复制速率、磁盘内挂载点间数据迁移速率、网络请求的线程数、处理请求的I/O线程数等等全局参数等等。

0.10.1.0~2.3.1版本都支持topics、clients、users、brokers四类型动态配置的11种粒度配置对象,只是配置模块和属性字段有增减与调整。

四、动态配置设计原理

用户使用kafka-configs.sh脚本,根据格式和参数规范要求,ConfigCommand类进行相关逻辑处理、json格式和内容校验,生成notification json,写入到序列化持久节点上,zk路径为

xxx/config/changes/config_change_seqNo,

节点名称为config_change_seqNo,其中seqNo从1开始的自增序号。kafka集群中所有broker通过监听zk上xxx/config/changes的children变化,每次获得比当前内存中last_seqNo大的seqNo的json内容,从中读取entity_type/entity_name相对路径,由此判断如何从xxx/config/topics|clients|users|brokers四种类型中读取哪个配置路径。同一个Broker在操作过程中任何时刻只能串行读写一种类型的配置,多种配置需要串行操作。

各个角色的作用:

kafka-config.sh: 负责写dynamic config和notification,写顺序上图有先后标识。broker:负责监听xxx/config/changes子节点变化和读取entity_type/entity_name路径节点上内容zk:负责存储notification和dynamic config及下发配置给相应的brokernotification json内容:V1 0.10.0.1及以前版本有效:

{    "version": 1,    "entity_type": "topics",    "entity_name":  "finalTest"}

V2 0.10.1.0~2.3.1 当前最新版本都有效

{    "version": 2,    "entity_path": "topics/finalTest"}

以上不管是version 1还是version2,本质上没有变化。都是通过entity_type/entity_name获得entity_path的zk相对路径,全路径为xxx/config/entityType/entityName,具体请看如下详图

entity_type=topics | clients | users | brokersentity_name=topicName | clientId | userId | (brokerId | )当entity_type为brokers时,brokerId为broker编号与自己的server.properties对应,只对某个broker生效。“”指对所有broker生效。而entity_type为topics | clients | users对所有broker都生效。通过以上entity_type/entity_name六种组合成六个zk相对路径。topics和clients组合原理一样,但users和brokers却略有不同,他们各自有2个组合,除了普通组合还有复合组合,两种类型组合在一起,例如users有users与clients组合,zk路径为users//clients/;brokers动态配置非常实用,不需要重启就能动态更改任意数量brokers配置,更改所有brokers为xxx/brokers/四类动态配置11种zk相对路径,根据11种zk相对路径可以读取11种粒度配置对象dynamic config。说明:某种类型下所有作用域生效,例如xxx/clients/和xxx/brokers/就是集群内所有All clients和集群内所有All brokers配置都会生效,其他同理。

dynamic config内容示例:

entity_type/entity_name=topics/=topics/finalTest

{    "version": 1,    "config": {        "retention.bytes": "102400000",        "flush.ms": "5000",        "cleanup.policy": "compact",        "flush.messages",        ...    }}

entity_type/entity_name=clients/=clients/camusall

{    "version": 1,    "config": {        "producer_byte_rate": "20971520",        "consumer_byte_rate": "20971520"    }}

entity_type/entity_name=brokers/all brokers=brokers/

{    "version": 1,    "config": {        "leader.replication.throttled.rate": "5000",        "follower.replication.throttled.rate": "60000",        "replica.alter.log.dirs.io.max.bytes.per.second": "5000",        "log.retention.hours": "24",        "log.flush.interval.messages": "5000",        "min.insync.replicas": "2",        ...    }}

entity_type/entity_name=brokers/brokerId     与all brokers的配置形成完全一样,只是作用域范围不同而已,此处省略。

写配置格式校验

如果写入配置不进行规范校验,broker就会读取处理过程中,就会卡住或阻塞,影响服务运行稳定性。所以配置校验至关重要,校验规则如下:

  • 配置项格式必须合法,否则报错不予接收

  • 输入配置项进行校验,输入参数必须是kafka包含的配置项,否则过滤掉

config_change_seqNo生成规则

kafka-configs.sh脚本每成功执行一次,在zk上就创建一个新的seqNode节点(即/xxx/config/changes/config_change_seqNo)seqNode是zk的持久顺序节点(PERSISTENT_SEQUENTIAL),它的组成是seqNode = seqNodePrefix + seqNodeSuffix,config_change_固定为seqNode的前缀,seqNodeSuffix = seqNo为seqNode的后缀,seqNo是10位数字的序列号,这个序列号后缀是自增的,由zk服务端自动生成和维护,每次事务请求成功就加1,它与MySQL的自增id原理一样。config_change_seqno清除原则

集群经过长期运行积累,xxx/config/changes下会留存大量历史节点,如果不及时清理,会有以下影响:

  • 大量无用的seqNode进行传输,会增加网络带宽负担

  • 占用zk服务端内存及存储资源

  • Kafka会做大量无效判断和计算

综上所述,因此必须要及时清除无用的seqNode集合,清除公式步骤如下:

  • 当broker监听到notification变化回调时,记录系统时间。

  • 获取xxx/config/changes下所有子节点,读取每个seqNode的创建时间

  • 系统时间减去seqNode创建时间,如果时间差值大于过期时间,即changeExpirationMs,就会被删除

  • changeExpirationMs默认为15分钟,可由broker配置。

config_change_seqno判断处理

前面提到每当触发回调处理,seqNode节点创建时间过期15分钟会被删除,删除条件是触发才会被执行,如果长时间不创建就可能有少数几个seqNode一直保留。如果短时间内(15分钟内)创建大量seqNode,又不会立即被删除,只有等到下次触发达到条件才行,那怎么判断哪些会被处理呢?broker缓存中维护一个变量lastExecutedSeqNo,它负责保存执行历史中seqNode最大顺序号,所以每当触发回调获取seqNodeSet列表时,都能轻易判断出哪些需要处理计算,也会同步更新lastExecutedSeqNo。

notification作用

  • 通知broker有新的动态配置产生,读取相应的动态配置
  • 不用监听大量四种类型配置下子节点,每个broker只需要监听一个notification节点即可,高效且性能也高
  • 大大减少broker监听数量,如果像controller监听/xxx/partitions/[0-N]/state一样,监听数量就是四种类型配置zk路径乘以broker数量了

静态与动态的配置及优先级

静态与动态区别。静态配置是Broker内置默认配置和静态配置文件server.properties,broker启动前可以任意修改,启动后不可修改。动态配置是broker启动运行后,可以在线更新生效,偷偷说一句离线也可以改,就是不生效而已。

配置优先级。以上4个图包含4类型配置既有动态也有静态,那优先级如何呢?动态配置优先级高于静态配置。如上图1、2、4,环越小优先级越高,对于动态配置来说修改配置作用域范围越小优先级越高,反之亦然。优先级最高的,会逐级覆盖相同配置参数。

当broker启动时。读取顺序依次为broker内置默认配置,broker静态配置文件,动态配置。当配置参数相同时,高优先级覆盖次优先的,其他依次类推

图示说明上图1、2、3、4中,其中图1、2、4中环数字表示配置优先级关系,数字从1~5表示优先级从高到低。图3为两级关联。Users和Clients组合实现配置管理,这两者组合用于客户端配额限流,Users与Clients就像两级目录一样,一个User可以包含一个、多个clientId或所有clientId。图4中既有优先级关系也有配置参数包含关系,topics类型配置是brokers类型配置的子集,brokers除了包含topic配置外还有DynamicThreadPool、DynamicListenerConfig、DynamicConnectionQuota、LogCleaner配置。

五、如何使用动态配置

  • 使用脚本kafka-configs.sh和kafka-topics.sh,kafka-configs.sh支持四种类型,kafka-topics.sh仅支持topics类型
  • 使用Apache-kafka官方提供的java版本客户端API调用
  • 直接写zk实现,具体遵循如上写notification和dynamic_config规范

如想更深入了解kafka-configs.sh用法,请查看脚本用法解析相关文章

六、总结

  • Kafka配置参数分为静态配置和动态配置,静态分为内置默认与外置用户配置,用户配置优先于内置配置
  • 动态配置为4类型11个zk相对路径,即11种粒度配置对象生效,同类型作用域范围越小优先级越高
  • 动态配置优先级比静态配置优先级高,动态配置中Users与Clients可以组合配置
  • 从设计原理中了解config_change_seqNo生成规则
  • 写上文中理解了写Notification的作用,从而理解什么场景会适合使用zk中持久顺序节点(PERSISTENT_SEQUENTIAL)

七、参考资料

https://www.cnblogs.com/lizherui/p/12056893.html

扫码关注

kafka原理_Kafka动态配置实现原理解析相关推荐

  1. 【kafka】Kafka中的动态配置源码分析

    1.概述 2.源码分析 Broker启动加载动态配置 KafkaServer.startup 启动加载动态配置总流程 2.1 动态配置初始化 config.dynamicConfig.initiali ...

  2. Nacos的动态配置源码解析

    文章目录 1. 如何使用 2. 原理详解 2.1 采用延迟线程池定时执行"监听"文件是否有修改 2.2 通过长轮询的方式获得修改过的文件及其内容 2.3 拿到配置后通过applic ...

  3. 动态磅是怎么原理_动态地磅的原理及发展

    动态地磅的原理及发展 发布时间:17/12/28 来源: 访问次数:4954 文章介绍了动态地磅的结构和工作原理,针对动态地磅的分类做了全面的概述,分别对不同的动态地磅做了对比 及详细的阐述,说明选择 ...

  4. python列表实现原理_Python动态类型实现原理及过程解析

    在python中,我们使用变量时,并没有声明变量的存在和类型.类型是在运行过程中自动决定的. a = 3 python将会执行三步去完成上面这个请求. 1.创建一个对象代表3 2.创建一个变量a,如果 ...

  5. mysql主原理_mysql 主从配置实现原理

    MySQL 本身通过 show slave status 提供了 Seconds_Behind_Master ,用于衡量主备之间的复制延迟,但是 今天碰到了一个场景,发现 Seconds_Behind ...

  6. Kafka启用SASL_PLAINTEXT动态配置JAAS文件的几种方式

    Kafka是广泛使用消息服务,很多情况下关于认证部分我都是默认的配置,也就是不需要用户名/密码,也不配置证书.在内网或者在项目组内部可以,但是设计的跨部门时一般处于安全考虑都需要加上认证,防止kafk ...

  7. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建

    为什么80%的码农都做不了架构师?>>>    kafka入门:简介.使用场景.设计原理.主要配置及集群搭建(转) 问题导读: 1.zookeeper在kafka的作用是什么? 2. ...

  8. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建--转载

    问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...

  9. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)

    问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...

最新文章

  1. FlycoTabLayout使用
  2. Python Django jsonpickle序列化隐藏部分字段代码示例
  3. srwebsocket 服务器过段时间会关闭_Minecraft 开启服务器后必须做的一些事情
  4. 《c语言从入门到精通》看书笔记——第3章 数据类型
  5. 有关 php __autoload 自动加载类函数的用法
  6. String Start!
  7. ios服务器需要开启ipv6的支持,针对iOS审核要求为应用兼容IPv6
  8. 一次关于使用status作为变量引发的bug及思考
  9. PB通过VDN实现Http上传、下载
  10. 基于ASP.NET的企业进销存管理系统
  11. FreebuF黑客专访系列之吴翰清(刺):接下来几年,有两样东西必定会火
  12. 回归中的相关度和R平方值——学习笔记
  13. 内网渗透之域内信息收集
  14. 抖音上线“冬季山货节”,不声不响把拼多多老家“偷了”?
  15. matlab外推法确定搜索区间的程序,《机械优化设计》复习题
  16. 字符串转utf8编码
  17. 2021年第十二届蓝桥杯省赛+国三C/C++B组参赛经历分享
  18. Gym 100712G Heavy Coins
  19. JWT授权为啥要在 Authorization标头里加个Bearer 呢
  20. 半自动微信消息定时发送

热门文章

  1. 京东物流基于Doris的亿级数据自助探索应用
  2. 某程序员吐槽:潮汕女朋友狮子大开口要18万8彩礼,而且只能男友父母出,不能男友出!...
  3. 一口气带你踩完五个 List 的大坑,真的是处处坑啊!
  4. 害怕离职,侧面说明大多数是离职了没人要的废物?
  5. 熬夜精心整理的一线大厂大数据、人工智能全套教程下载(含视频+源码)!!...
  6. 玩转飞书日历,体验高效办公!
  7. 站长新手入门:从0开始搭建微信小程序商城,不会代码也能开商城(附带源码)
  8. 种子之父--布莱恩-科恩
  9. TF (transform) in ROS
  10. t6文件服务器怎么设置,t6 修改文件服务器地址