Kafka基本原理(五)配置

kafka配置很多,分Broker配置、Topic配置、producer配置、consumer配置、Connect配置、AdminClient配置。详细内容见kafka中文官网。其中,很多配置并不需要修改,除非有需要使用默认值更好。

1.Broker配置

核心基础配置

  • broker.id         用于服务的broker id。如果没设置,将生存一个唯一broker id。
  • log.dirs         保存日志数据的目录
  • zookeeper.connect   Zookeeper主机地址

2.生产者配置

  1. ackstimeout.ms
  • timeout.ms(0.9.0.0版本中就被弃用)
    指定了 broker 等待同步副本返回消息确认的时间,与 asks 的配置相匹配——如果在指定时间内没有收到同步副本的确认,那么 broker 就会返回一个错误。

  • acks = 1
    指定了必须要有多少个分区副本收到消息,生产者才会认为消息写入是成功的。这个参数对消
    息丢失的可能性有重要影响。该参数有如下选项:

    • acks=0,生产者在成功写入消息之前不会等待任何来自服务器的响应。也就是说,如果当中
      出现了问题,导致服务器没有收到消息,那么生产者就无从得知,消息也就丢失了。不过,因为
      生产者不需要等待服务器的响应,所以它可以以网络能够支持的最大速度发送消息,从而达到很
      高的吞吐量。
    • acks=1,只要集群的 Leader 节点收到消息,生产者就会收到一个来自服务器的成功响应。如果消息无法到达 Leader 节点(比如首领节点崩溃,新的 Leader 还没有被选举出来),生产者会收到一个错误响应,为了避免数据丢失,生产者会重发消息。不过,如果一个没有收到消息的节点成为新Leader,消息还是会丢失。这个时候的吞吐量取决于使用的是同步发送还是异步发送。如果让发送客户端等待服务器的响应(通过调用 Future 对象的 get() 方法),显然会增加延迟(在网络上传输一个来回的延迟)。如果客户端使用回调,延迟问题就可以得到缓解,不过吞吐量还是会受发送中消息数量的限制(比如,生产者在收到服务器响应之前可以发送多少个消息)。

    • 如果 acks=all,只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。这种模式是最安全的,它可以保证不止一个服务器收到消息,就算有服务器发生崩溃,整个集群仍然可以运行。不过,它的延迟比 acks=1 时更高,因为我们要等待不只一个服务器节点接收消息。

  1. buffer.memory=33554432
    该参数用来设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息。如果生产消息的速度超过发送的速度,会导致生产者空间不足。这个时候, send()方法调用要么被阻塞,要么抛出异常,取决于如何设置 block.on.buffer.full 参数(在 0.9.0.0 版本里被替换成了max.block.ms,表示在抛出异常之前可以阻塞一段时间)

  2. compression.type=none
    默认情况下,消息发送时不会被压缩。该参数可以设置为 snappygziplz4,它指定了消息被发送给 broker 之前使用哪一种压缩算法进行压缩。

  • snappy 压缩算法由 Google 发明,占用较少的 CPU,却能提供较好的性能和相当可观的压缩比,如果比较关注性能和网络带宽,可以使用这种算法。
  • gzip 压缩算法一般会占用较多的 CPU,但会提供更高的压缩比,所以如果网络带宽比较有限,可以使用这种算法。

使用压缩可以降低网络传输开销和存储开销,而这往往是向 Kafka 发送消息的瓶颈所在。

  1. retriesretry.backoff.ms
  • retries=0
    生产者从服务器收到的错误有可能是临时性的错误(比如分区找不到 Leader)。在这种情况下,retries
    参数的值决定了生产者可以重发消息的次数,如果达到这个次数,生产者会放弃重试并返回错误。

  • retry.backoff.ms=100
    默认情况下,生产者会在每次重试之间等待 100ms,不过可以通过 retry.backoff.ms 参数来改变这个时间间隔。建议在设置重试次数和重试时间间隔之前,先测试一下恢复一个崩溃节点需要多少时间(比如所有分区选举出 Leader 需要多长时间),让总的重试时间比 Kafka 集群从崩溃中恢复的时间长,否则生产者会过早地放弃重试。

  • 不过有些错误不是临时性错误,没办法通过重试来解决(比如“消息太大”错误)。一般情况下,因为生产者会自动进行重试,所以就没必要在代码逻辑里处理那些可重试的错误。你只需要处理那些不可重试的错误和重试次数超出上限的情况。

  1. batch.sizelinger.ms
  • batch.size:=16384
    当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算(而不是消息个数)。
  • linger.ms:=0
    指定了生产者在每次发送消息的时间间隔

当批次被填满 或者 等待时间达到 linger.ms设置的间隔时间,批次里的所有消息会被发送出去,哪怕此时该批次只有一条消息。
所以就算把批次大小设置得很大,也不会造成延迟,只是会占用更多的内存而已。但如果设置得太小,因为生产者需要更频繁地发送消息,会增加一些额外的开销。

  1. client.id=''
    该参数可以是任意的字符串,服务器会用它来识别消息的来源

  2. max.in.flight.requests.per.connection=5
    该参数指定了生产者在收到服务器响应之前可以发送多少个消息。它的值越高,就会占用越多的内存,不过也会提升吞吐量。把它设为 1 可以保证消息是按照发送的顺序写入服务器的,即使发生了重试。

如何保证顺序性:如果把 retries 设为非零整数,同时把 max.in.flight.requests.per.connection 设为比 1 大的数,那么,如果第一个批次消息写入失败,而第二个批次写入成功,broker 会重试写入第一个批次。如果此时第一个批次也写入成功,那么两个批次的顺序就反过来了。

一般来说,如果某些场景要求消息是有序的,那么消息是否写入成功也是很关键的,所以不建议把retries设为 0。可以把 max.in.flight.requests.per.connection 设为 1,这样在生产者尝试发送第一批消息时,就不会有其他的消息发送给broker。不过这样会严重影响生产者的吞吐量,所以只有在对消息的顺序有严格要求的情况下才能这么做。

  1. request.timeout.msmetadata.fetch.timeout.ms
  • request.timeout.ms=305000
    指定了生产者在发送数据时等待服务器返回响应的时间
  • metadata.fetch.timeout.ms (0.9.0.0版本中就被弃用)
    指定了生产者在获取元数据(比如目标分区的 Leader 是谁)时等待服务器返回响应的时间。如果等待响应超时,那么生产者要么重试发送数据,要么返回一个错误(抛出异常或执行回调)。
  1. max.request.size=1048576
    该参数用于控制生产者发送的请求大小。它可以指能发送的单个消息的最大值,也可以指单个请求里所有消息总的大小。例如,假设这个值为 1MB,那么可以发送的单个最大消息为 1MB,或者生产者可以在单个请求里发送一个批次,该批次包含了 1000 个消息,每个消息大小为 1KB。另外,broker 对可接收的消息最大值也有自己的限制(message.max.bytes),所以两边的配置最好可以匹配,避免生产者发送的消息被 broker 拒绝。

注意区分 batch.size只是针对一个 topic 的 partition,而 max.request.size针对单次请求的。

  1. receive.buffer.bytes=32768 和 send.buffer.bytes=131072
    这两个参数分别指定了 TCP socket 接收和发送数据包的缓冲区大小。如果它们被设为 -1,就使用操作系统的默认值。如果生产者或消费者与 broker 处于不同的数据中心,那么可以适当增大这些值,因为跨数据中心的网络一般都有比较高的延迟和比较低的带宽。

3.消费者常用配置

(1) fetch.min.bytes

  • 类型:int
  • 默认值:1
  • 可设置值:[0,...]
  • 重要性:高
  • 说明:该属性指定了消费者从服务器获取记录的最小字节数。broker 在收到消费者的数据请求时,如果可用的数据量小于 fetch.min.bytes 指定的大小,那么它会等到有足够的可用数据时才把它返回给消费者。这样可以降低消费者和 broker 的工作负载,因为它们在主题不是很活跃的时候(或者一天里的低谷时段)就不需要来来回回地处理消息。如果没有很多可用数据,但消费者的 CPU 使用率却很高,那么就需要把该属性的值设得比默认值大。如果消费者的数量比较多,把该属性的值设置得大一点可以降低 broker 的工作负载。

(2) fetch.max.wait.ms

  • 类型:int
  • 默认值:500
  • 可设置值:[0,...]
  • 重要性:低
  • 说明:我们通过 fetch.min.bytes 告诉 Kafka,等到有足够的数据时才把它返回给消费者。而 feth.max.wait.ms 则用于指定 broker 的等待时间,默认是如果没有足够的数据流入Kafka,消费者获取最小数据量的要求就得不到满足,最终导致 500ms 的延迟。如果 fetch.max.wait.ms 被设为 100ms,并且 fetch.min.bytes 被设为 1MB,那么 Kafka 在收到消费者的请求后,要么返回 1MB 数据,要么在 100ms 后返回所有可用的数据,就看哪个条件先得到满足。

(3) max.partition.fetch.bytes

  • 类型:int
  • 默认值:1048576
  • 可设置值:[0,...]
  • 重要性:高
  • 说明:该属性指定了服务器从每个分区里返回给消费者的最大字节数。它的默认值是 1MB,也就是说,KafkaConsumer.poll() 方法从每个分区里返回的记录最多不超过 max.partition.fetch.bytes 指定的字节。如果一个主题有20个分区和5个消费者,那么每个消费者需要至少 4MB 的可用内存来接收记录。在为消费者分配内存时,可以给它们多分配一些,因为如果群组里有消费者发生崩溃,剩下的消费者需要处理更多的分区。max.partition.fetch.bytes 的值必须比 broker 能够接收的最大消息的字节数(通过 max.message.size 属性配置)大,否则消费者可能无法读取这些消息,导致消费者一直挂起重试。在设置该属性时,另一个需要考虑的因素是消费者处理数据的时间。消费者需要频繁调用 poll() 方法来避免会话过期和发生分区再均衡,如果单次调用 poll() 返回的数据太多,消费者需要更多的时间来处理,可能无法及时进行下一个轮询来避免会话过期。如果出现这种情况,可以把 max.partition.fetch.bytes 值改小,或者延长会话过期时间。

(4) session.timeout.ms

  • 类型:int
  • 默认值:10000
  • 重要性:high
  • 说明:该属性指定了消费者在被认为死亡之前可以与服务器断开连接的时间,默认是 1s。如果消费者没有在 session.timeout.ms 指定的时间内发送心跳给群组协调器,就被认为已经死亡,组协调器就会触发再均衡,把它的分区分配给群组里的其他消费者。该属性与heartbeat.interval.ms紧密相关。heartbeat.interval.ms 指定了 poll() 方法向协调器发送心跳的频率,session.timeout.ms 则指定了消费者可以多久不发送心跳。所以,一般需要同时修改这两个属性,heartbeat.interval.ms 必须比 session.timeout.ms 小,一般是 session.timeout.ms 的三分之一。如果 session.timeout.ms 是 3s,那么 heartbeat.interval.ms 应该是 1s。把 session.timeout.ms 值设得比默认值小,可以更快地检测和恢复崩溃的节点,不过长时间的轮询或垃圾收集可能导致非预期的再均衡。把该属性的值设置得大一些,可以减少意外的再均衡,不过检测节点崩溃需要更长的时间。

(5) auto.offset.reset

  • 类型:latest
  • 默认值:string
  • 可设置值:[latest, earliest, none]
  • 重要性:中等
  • 说明:该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下(因消费者长时间失效,包含偏移量的记录已经过时并被删除)该作何处理。它的默认值是 latest,意思是说,在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录)。另一个值是 earliest,意思是说,在偏移量无效的情况下,消费者将从起始位置读取分区的记录。none 则代表当偏移量失效后,直接抛出异常。

(6) enable.auto.commit

  • 类型:boolean
  • 默认值:true
  • 重要性:中等
  • 说明:该属性指定了消费者是否自动提交偏移量,默认值是 true。为了尽量避免出现重复数据和数据丢失,可以把它设为 false,由自己控制何时提交偏移量。如果把它设为 true,还可以通过配置 auto.commit.interval.ms 属性来控制提交的频率。

(7) partition.assignment.strategy

  • 类型:list
  • 默认值:org.apache.kafka.clients.consumer.RangeAssignor
  • 可设置值:
    org.apache.kafka.clients.consumer.RangeAssignor
    org.apache.kafka.clients.consumer.RoundRobinAssignor
    自定义的策略
  • 重要性:中等
  • 说明:PartitionAssignor 根据给定的消费者和主题,决定哪些分区应该被分配给哪个消费者。Kafka 有两个默认的分配策略。
    • Range:该策略会把主题的若干个连续的分区分配给消费者。假设消费者 C1 和消费者 C2 同时订阅了主题 T1 和主题 T2,并且每个主题有 3 个分区。那么消费者 C1 有可能分配到这两个主题的分区 0 和分区 1,而消费者 C2 分配到这两个主题的分区2。因为每个主题拥有奇数个分区,而分配是在主题内独立完成的,第一个消费者最后分配到比第二个消费者更多的分区。只要使用了 Range 策略,而且分区数量无法被消费者数量整除,就会出现这种情况。
    • RoundRobin:该策略把主题的所有分区逐个分配给消费者。如果使用 RoundRobin 策略来给消费者 C1 和消费者 C2 分配分区,那么消费者 C1 将分到主题 T1 的分区 0 和分区 2 以及主题 T2 的分区 1,消费者 C2 将分配到主题 T1 的分区 1 以及主题 T2 的分区 0 和分区 2。一般来说,如果所有消费者都订阅相同的主题(这种情况很常见),RoundRobin 策略会给所有消费者分配相同数量的分区(或最多就差一个分区)。

(8) client.id

  • 类型:string
  • 默认值:""
  • 重要性:低
  • 说明:该属性可以是任意字符串,代表消费的ID,broker 用它来标识从客户端发送过来的消息

(9) max.poll.records

  • 类型:int
  • 默认值:500
  • 可设置值:[1,...]
  • 重要性:中等
  • 说明:该属性用于控制单次调用 poll() 方法最多能够返回的记录条数,可以帮你控制在轮询里需要处理的数据量。

(10) receive.buffer.bytes 和 send.buffer.bytes

receive.buffer.bytes

  • 类型:int
  • 默认值:65536(64K)
  • 可设置值:[-1,...]
  • 重要性:中等

send.buffer.bytes

  • 类型:int
  • 默认值:131072(128K)
  • 可设置值:[-1,...]
  • 重要性:中等

说明:这两个参数分别指定了 TCP socket 接收和发送数据包的缓冲区大小。如果它们被设为 -1,就使用操作系统的默认值。如果生产者或消费者与 broker 处于不同的数据中心,那么可以适当增大这些值,因为跨数据中心的网络一般都有比较高的延迟和比较低的带宽

参考:

https://www.jianshu.com/p/4297ad291f1a

https://www.jianshu.com/p/48eddba198fa

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值