关于kafka配额的讨论

huxi_2b huxi_2b     2022-10-26     669

关键词:

Kafka自0.9.0.0版本引入了配额管理(quota management),旨在broker端对clients发送请求进行限流(throttling)。目前Kafka支持两大类配额管理:

  • 网络带宽(network bandwidth)配额管理:定义带宽阈值来限制请求发送速率,阈值单位是字节/秒,即bytes/s。该功能是0.9.0.0版本引入的
  • CPU配额管理:定义CPU使用率阈值来限制请求发送速率,阈值以百分比的形式给出,如quota = 50表示50%的CPU使用率上限。该功能是0.11.0.0版本引入的

本文主要讨论网络带宽配额管理。关于CPU配额管理的部分我们将在下一篇中进行讨论。

一、配额能做什么?

设置了基于带宽的配额之后,Kafka能够做到:

1. 限制follower副本拉取leader副本消息的速率

2. 限制producer的生产速率

3. 限制consumer的消费速率

二、配额作用域

目前可以在3个层级上设置配额:

1. client id

2. user 

3. user + client id

第一种是client id,即新版本clients端的通用参数client.id设置的值。一旦为某个client id设置了配额,所有具有该client id的clients段程序都将受到该配额的限制。

第二种是user,为启用认证之后位于认证体系中的某个用户主体(user principal),比如一个Kerberos用户:user1/[email protected],Kafka解析出来的用户名是‘user1’。当然我们可以设置sasl.kerberos.principal.to.local.rules参数修改这种解析规则,不过这不在本文的讨论范围内。

第三种就是user + client id,实际上是包含前两种的一个二元组。它是最细粒度化的配额管理作用域。

当然,这3种作用域还可以设置各自的默认值配额(默认是没有配额的,即默认值通常是无穷大),包括:client id作用域默认值、user作用域默认值、user + client id作用域默认值,其中最后一项又可细分为4个子作用域,即

  • user作用域默认值 + client id作用域指定值
  • user作用域指定值 + client id作用域指定值
  • user作用域默认值 + client id作用域默认值
  • user作用域指定值 + client id作用域默认值

因此,实际上总共有8种可能的配额作用域设置值,它们的优先级关系依次如下(从高到低):

  • user作用域指定值 + client id作用域指定值(即为user + client id设置了特定值配额)
  • user作用域指定值 + client id作用域默认值(为user设置了特定值配额,为client id设置了默认值配额)
  • user作用域(为user设置了特定值配额)
  • user作用域默认值 + client id作用域指定值(为user设置了默认值配额,为client id设置了特定值配额)
  • user作用域默认值 + client id作用域默认值(为user和client id设置了默认值配额)
  • user作用域默认值(为user设置了默认值配额)
  • client id作用域(为client id设置了特定值配额)
  • client id作用域默认值(为client id设置了默认值配额)

当多条配额规则冲突时我们可以根据以上规则确定应用的是哪一条。举个例子,我们为user = ‘good-user‘的用户配置了100MB/s的配额,同时为[user=‘good-user‘, client id = ‘producer-1‘]设置配额为50MB/s,那么当good-user用户使用名为‘producer-1’的producer发送消息时Kafka保证它的请求处理速率不会超过50MB/s,即第二条规则覆盖了第一条规则。

三、如何设置?

我们根据第一小节中提到的3种功能来分别讨论。

3.1 限制follower副本拉取leader副本消息的速率

方法1: 设置broker端动态参数leader.replication.throttled.rate和follower.replication.throttled.rate。

前者控制leader副本端处理FETCH请求的速率,后者控制follower副本发送FETCH请求的速率。既然是动态参数,说明它们的值可以实时修改而无需重启broker。假设我要为broker 0和1设置follower和leader限速为100MB/s,方法如下:

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘leader.replication.throttled.rate=104857600,follower.replication.throttled.rate=104857600‘ --entity-type brokers --entity-name 0
Completed Updating config for entity: brokers ‘0‘.

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘leader.replication.throttled.rate=104857600,follower.replication.throttled.rate=104857600‘ --entity-type brokers --entity-name 1
Completed Updating config for entity: brokers ‘1‘.

执行下列命令检查下是否配置成功:

bin/kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type brokers
Configs for brokers ‘0‘ are leader.replication.throttled.rate=104857600,follower.replication.throttled.rate=104857600
Configs for brokers ‘1‘ are leader.replication.throttled.rate=104857600,follower.replication.throttled.rate=104857600

 方法2:执行分区重分配时设置

在使用kafka-reassign-partitions.sh(bat)脚本执行分区重分配时也可以设定 ,方法如下(依然设置成100MB/s):

 bin/kafka-reassign-partitions.sh --zookeeper localhost:2181  --execute --reassignment-json-file to-be-reassigned.json --throttle 104857600

实际上,该脚本通过--throttle参数间接设置了leader.replication.throttled.rate和follower.replication.throttled.rate参数,故本质上和方法1是相同的。值得注意的,该脚本只会对参与到分区重分配的broker设置配额,对其他broker是不起作用的。

3.2 限制producer端速率

方法1: 设置broker端静态参数quota.producer.default参数

比如:在server.properties中加入quota.producer.default=15728640将限制所有连入该broker的producer的TPS全部降到15MB/s以下。设置此参数的好处是能够限制集群上的所有producer,但劣处也在于此,对所有producer“一视同仁”,无法细粒度地对个别clients进行设置。故社区在0.11.0.0版本将其标记为"Deprecated",并始终推荐用户使用动态参数的方式来为producer端进行限速。

方法2:设置动态参数producer_byte_rate

首先演示为所有client id设置默认值,假设我们为所有producer程序设置其TPS不超过20MB/s,即20971520B/s,命令如下:

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type clients --entity-default
Completed Updating config for entity: default client-id.

然后我们为client.id=‘producer-1‘的producer单独设置其TPS不超过10MB/s,即10485760B/s,命令如下:

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=10485760‘ --entity-type clients --entity-name producer-1
Completed Updating config for entity: client-id ‘producer-1‘.

下面做个简单的试验验证下,我们启动两个client.id是producer-1和producer-2的producer程序去验证它们的TPS小于设置的阈值:

bin/kafka-producer-perf-test.sh --topic t1 --throughput -1 --num-records 9000000 --record-size 500 --producer-props bootstrap.servers=localhost:9092 acks=-1 client.id=producer-2
......
9000000 records sent, 41632.936278 records/sec (19.85 MB/sec), 1563.41 ms avg latency, 6488.00 ms max latency, 912 ms 50th, 5576 ms 95th, 6169 ms 99th, 6474 ms 99.9th.

可见producer-2的TPS被限制在了20MB/s以下。接下来我们试试producer-1(因为其阈值设置得小,故这次我们少发一些消息以加速整个试验进程):

bin/kafka-producer-perf-test.sh --topic t1 --throughput -1 --num-records 3000000 --record-size 500 --producer-props bootstrap.servers=localhost:9092 acks=-1 client.id=producer-1
......
3000000 records sent, 20771.020273 records/sec (9.90 MB/sec), 3128.39 ms avg latency, 8960.00 ms max latency, 986 ms 50th, 8784 ms 95th, 8941 ms 99th, 8953 ms 99.9th.

为user设置配额的方法与client id类似,设置全局默认值:

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type users --entity-default
Completed Updating config for entity: default user-principal.

为特定用户(user1)设置:

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type users --entity-name user1

Completed Updating config for entity: user-principal ‘user1‘.

最后是设置(user + client id)作用域设置配额。依然是全局默认值:

user1的client id默认配额

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type users --entity-name user1 --entity-type clients --entity-default
Completed Updating config for entity: user-principal ‘user1‘, default client-id.

producer-1的user默认配额

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type users --entity-default --entity-type clients --entity-name producer-1
Completed Updating config for entity: default user-principal, client-id ‘producer-1‘.

然后是特定值:

user1 + producer-1的配额值

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config ‘producer_byte_rate=20971520‘ --entity-type users --entity-name user1 --entity-type clients --entity-name producer-1
Completed Updating config for entity: user-principal ‘user1‘, client-id ‘producer-1‘.

3.3 限制consumer端速率

和producer类似,也存在两种方法:

方法1: 设置broker端静态参数quota.consumer.default参数

与quota.producer.default完全相同的参数,只不过是适用于consumer端的,不再赘述。

方法2:设置动态参数consumer_byte_rate

与producer_byte_rate完全对等的参数,只是适用于consumer端的,不再赘述

四、配额算法

简单来说,我们假设当前实际值是O,T是我们设置的阈值,而W表示某一段时间范围,我们希望在W时间内O能够下降到T以下(如果O本来就比T小,则什么都不用做),那么broker端就需要延缓等待一段时间。如果假设这段时间是X,那么以下等式成立:

O * W = (W + X) * T 

由此得出X = (O - T) / T * W。这就是Kafka用于计算等待时间的公式。当然在具体实现时,Kafka提供了两个参数来共同计算W:W = quota.window.num * quota.window.size.seconds。前者表示取样的时间窗口个数,后者表示时间窗口大小。特别是后者会在CPU配额管理中用到。不过在本文中,我们可以统一使用W即可。当Kafka检测到配额透支情况发生时,broker不会返回错误而是直接将超支配额的客户端进行减速处理。它会计算需要X然后令client强制sleep直至令其降到配额之下。该方法对于client来说完全透明。同时,client也不需要自己实现任何特殊的策略来应对。事实上,有的client在应对这种情况时会不停地重试反而加剧了本要解决的问题。

五、可能的问题

如前所述,限速是在broker端执行的!broker端故意“sleep”来限速的做法虽然对clients端透明,但确实也会引起clients端请求的超时,故在实际使用过程中适当地增加request.timeout.ms对于启用了限速的Kafka环境而言就显得非常必要了。

kafka关于kafkafetchsession的讨论(代码片段)

1.概述转载:关于KafkaFetchSession的讨论Kafka在1.1.0版本引入了fetchsession的概念,旨在降低“无效”FETCH请求对集群带宽资源的占用。故事的背景是这样的:众所周知,Kafka的broker和consumer都会定期地向leaderbroker发送FETCH... 查看详情

关于kafka幂等producer的讨论

  众所周知,Kafka0.11.0.0版本正式支持精确一次处理语义(exactlyoncesemantics,下称EOS)。Kafka的EOS主要体现在3个方面:幂等producer:保证发送单个分区的消息只会发送一次,不会出现重复消息事务(transaction):保证原子性地写入到多... 查看详情

kafka--关于高水位和leaderepoch的讨论

什么是高水位?        在Kafka的世界中,水位的概念有一点不同。Kafka的水位不是时间戳,更与时间无关。它是和位置信息绑定的,具体来说,它是用消息位移来表征的。用来区分已消费和未消费数据。&#x... 查看详情

2021年大数据kafka:❤️kafka配额限速机制❤️(代码片段)

...f0c;帮助大家回顾前面的知识重点。目录系列历史文章Kafka配额限速机制限制producer端的速率限制consumer端的速率取消kafka的Quota配置系列历史文章2021年大数据Kafka(十二):❤️Kafka配额限速机制 查看详情

kafka的客户端限流(资源配额)(代码片段)

...户端限流在kafka的官方文档,不叫限流,叫做资源配额:通过对客户端请求进行配额,控制集群资源的使用。主要支持以下两种类型:带宽(从0.9版本开始)请求 查看详情

关于kafka__consumer_offests的讨论

 众所周知,__consumer__offsets是一个内部topic,对用户而言是透明的,除了它的数据文件以及偶尔在日志中出现这两点之外,用户一般是感觉不到这个topic的。不过我们的确知道它保存的是Kafka新版本consumer的位移信息。本文我们... 查看详情

2021年大数据kafka:❤️kafka配额限速机制❤️(代码片段)

...f0c;帮助大家回顾前面的知识重点。目录系列历史文章Kafka配额限速机制限制producer端的速率限制consumer端的速率取消kafka的Quota配置系列历史文章2021年大数据Kafka(十二):❤️Kafka配额限速机制❤️2021年大数据Kafkaÿ... 查看详情

kafka的客户端限流(资源配额)(代码片段)

...户端限流在kafka的官方文档,不叫限流,叫做资源配额:通过对客户端请求进行配额,控制集群资源的使用。主要支持以下两种类型:带宽(从0.9版本开始)请求速率(从0.11版本开始)带宽就是基于每秒传输多少个... 查看详情

kafka中的消费组

一直以来都想写一点关于kafkaconsumer的东西,特别是关于新版consumer的中文资料很少。最近Kafka社区邮件组已经在讨论是否应该正式使用新版本consumer替换老版本,笔者也觉得时机成熟了,于是写下这篇文章讨论并总结一下新版本co... 查看详情

kafka消费组(consumergroup)

一直以来都想写一点关于kafkaconsumer的东西,特别是关于新版consumer的中文资料很少。最近Kafka社区邮件组已经在讨论是否应该正式使用新版本consumer替换老版本,笔者也觉得时机成熟了,于是写下这篇文章讨论并总结一下新版本co... 查看详情

关于kafkabrokerio的讨论

  ApacheKafka是大量使用磁盘和页缓存(pagecache)的,特别是对pagecache的应用被视为是Kafka实现高吞吐量的重要因素之一。实际场景中用户调整pagecache的手段并不太多,更多的还是通过管理好broker端的IO来间接影响pagecache从而实现高... 查看详情

关于linux磁盘配额的奇怪问题

我给admin用户启用了/mnt/配额、也成功限制了、但是quota-uadmin显示none也就是什么都没有、repquota/mnt/也没有、只有默认的root的配额、请问怎么回事啊、谢谢!EL5为例,也只有根分区与交换分区)步聚如下:1、首先修改“/etc/fstab”... 查看详情

关于kafka数据丢失场景的一次激烈讨论....

参考技术A问题描述最近彦祖发现,有不少同学对acks和min.insync.replicas的配置存在不少误解.刚好拿一个同学的问题,来好好说明一下根据上面提的几个问题,整理一下几个知识点acks=all的概念是什么?min.insync.replicas是怎么用的?什么... 查看详情

求寒冰老师的linux教程,有关磁盘限额的讲解

...件数量。要实现磁盘配额,quotaRPM必须在系统上被安装。关于安装RPM软件包的详情,请参阅第III部分。6.1.配置磁盘配额要实现磁盘配额,请使用以下步骤:修改/etc/fstab来启用每个文件系统的配额重新挂载文件系统创建配额文件... 查看详情

kafka水位(highwatermark)与leaderepoch的讨论

...就是位置信息,即位移(offset)。网上有一些关于Kafkawatermark的 查看详情

关于 kafka 中的日志记录系统的信息

】关于kafka中的日志记录系统的信息【英文标题】:Informationaboutloggingsysteminkafka【发布时间】:2022-01-2312:10:03【问题描述】:我正在尝试查找有关kafka中日志记录系统的信息,哪些日志写入controller.log、log-cleaner.log、kafka-request.log... 查看详情

Grafana:如何获取关于 kafka 内部主题的数据?

】Grafana:如何获取关于kafka内部主题的数据?【英文标题】:Grafana:howtogetdataaboutinternaltopicsofkafka?【发布时间】:2021-08-2410:58:39【问题描述】:我想以__consumer_offsets主题的速率获取消息。但是如果我把这个查询放在grafana中:rate(k... 查看详情

kafka水位(highwatermark)与leaderepoch的讨论

Kafka水位(highwatermark)与leaderepoch的讨论~~~这是一篇有点长的文章,希望不会令你昏昏欲睡~~~本文主要讨论0.11版本之前Kafka的副本备份机制的设计问题以及0.11是如何解决的。简单来说,0.11之前副本备份机制主要依赖水位(或... 查看详情