7、关于KafkaConsumer

一、新旧API的区别

老版本(0.8及以前)Consumer会在zookeeper上记录和管理group信息,一旦consumer挂了,其他所有consumer都会接收到信息,会重新进行rebenlance

新版本(0.9及以上)kafka,每个broker都会有一个groupCoordinator,每个consumer都会有一个consumerCoordinator,并且引入了topic:__consumer_offsets来存储group信息,减轻zookeeper压力。

注意:__consumer_offsets topic不是broker集群启动就创建的,而是第一次消费时才会创建。service.properties中关于此topic的配置:partitions=50,offsets.topic.replication.factor=1

此时zookeeper上/consumers下没有group相关的信息了

二、分区分配算法

多个consumer同时消费一个topic,partition怎么分配? ==> 不管新版本还是旧版本,都提供了两种分区分配算法,都能确保一个partition只能给一个consumer线程消费,多余的consumer线程无法拿到数据。

  • 1、kafka.consumer.RangeAssignor.java (这个是默认的,代码就不贴出来了,太多,自己用ide来看)

    针对每一个topic进行计算,topic之间没有关联,算法逻辑如下:

      1、先得到topic的有效分区数n,获取订阅了这个topic的所有消费者线程数m。
      2、n / m 得到每个线程得到的分区数,剩下的余数分别给前面几个线程,一个线程多一个。
    

    举例子:

      现在有topic T0,有分区[P0, P1, P2, P3, P4, P5, P6]
                 topic T1,有分区[P0, P1, P2, P3, P4, P5, P6]
                 3个消费者线程(comsumer0, consumer1, consumer2)来消费,流程图如下:l
    

  • 2、kafka.consumer.RoundRobinAssignor.java (代码就不贴出来了,太多,自己用ide来看)

    也是针对每一个topic的所有分区进行处理,但是并不像上一个那样,每个topic都第一个consumer开始进行分配,而是循环遍历consumer,到哪个就是那个

      1、获取groupID下订阅所有topic的有效分区,并且按照topic以及partitions进行排序,topicParMap
      2、获取groupID下所有consumer,以及每个consumer订阅的topic,consumerTopicMap
      3、循环遍历topicParMap,里面在循环遍历consumerTopicMap,如果consumer订阅了本topic,就把此partition给它,否则继续下一个consumer
    

    举例子

      现同样有上述的条件,流程图如下(重点是T0的P6分配给consumer1后,T1的P0分配给了consumer2,从而T1的P6就会分配给了consumer2)
    

  • 3、自定义分配类(一般用不上)

    最简单的方式就是直接继承RangeAssignor或者RoundRobinAssignor,然后重写assign方法即可,或者和这两个类一样,直接实现PartitionAssignor也可以

    最后在kafka consumer代码的参数配置那里配置上即可

      public static ConsumerConfig initConf(){
          Properties param = new Properties();
          param.setProperty("zookeeper.connect", "192.168.0.186:2181,192.168.0.187:2181,192.168.0.189:2181,192.168.0.190:2181/kafka");
          param.setProperty("group.id", "testGroup");
          param.setProperty("auto.offset.reset", "largest");
    
          // 设置自定义分区分配器
       param.setProperty("partition.assignment.strategy", "com.study.kafka.MyAssignor");
    
          return new ConsumerConfig(param);
      }
    

三、关于协调器coordinate

1、两个协调器,以及工作流程

每一个broker都有一个groupCoordinator,每一个consumer都有一个consumerCoordinator。

consumerCoordinator发送findCoordinator给任何一个broker
broker接收到后计算groupID.hash % 50  ==> __consumer_offsets对应分区,此分区所在broker就是此groupID对应的groupCoordinator
consumerCoordinator向groupCoordinator发送joinGroup请求加入group
consumerCoordinator向groupCoordinator发送sync请求获取自己分配到的partition
每间隔3S和groupCoordinator保持心跳
定时commit  offset 给groupCoordinator,由它写入到__consumer_offsets

2、相关参数

  • heartbeat.interval.ms

    心跳间隔。心跳是在 consumer 与 coordinator 之间进行的。心跳是确定 consumer 存活,加入或者退出 group 的有效手段。这个值必须设置的小于 session.timeout.ms,因为当 consumer 由于某种原因不能发 heartbeat 到 coordinator 时,并且时间超过 session.timeout.ms 时,就会认为该 consumer 已退出,它所订阅的 partition 会分配到同一 group 内的其它的 consumer 上。

    默认值:3000 (3s),通常设置的值要低于session.timeout.ms的1/3。

  • session.timeout.ms

    consumer session 过期时间。如果超时时间范围内,没有收到消费者的心跳,broker 会把这个消费者置为失效,并触发消费者负载均衡。因为只有在调用 poll 方法时才会发送心跳,更大的 session 超时时间允许消费者在 poll 循环周期内处理消息内容,尽管这会有花费更长时间检测失效的代价。如果想控制消费者处理消息的时间,

    默认值:10000 (10s),这个值必须设置在 broker configuration 中的 group.min.session.timeout.ms 与 group.max.session.timeout.ms 之间。

  • max.poll.interval.ms

    参数设置大一点可以增加两次 poll 之间处理消息的时间。

    当 consumer 一切正常(也就是保持着 heartbeat ),且参数的值小于消息处理的时长,会导致 consumer leave group 然后又 rejoin group,触发无谓的 group balance,出现 consumer livelock 现象。

    但如果设置的太大,会延迟 group rebalance,因为消费者只会在调用 poll 时加入rebalance。

  • max.poll.records

      max.poll.interval.ms=5min
      max.poll.records=500
    

    即平均 600ms 要处理完一条消息,如果消息的消费时间高于 600ms,则一定要调整 max.poll.records 或 max.poll.interval.ms。

  • fetch.min.bytes=1

      consumer去获取数据,如果不够1M了,则broker会延迟等待
    

四、相关问题

  • 1、一个kafkaConsumer对象 不能给多线程并发访问,会报错

      KafkaConsumer is not safe for multi-threaded access
    

    而producer就可以

    实现原理:不是使用锁,而是使用前先判断是不是有人正在使用,如果是则报错

  • 2、本机器hosts文件必须配置broker的ip映射,否则拿不到数据,也不会报错

  • 3、旧版本kafka consumer offset在zk上的位置

      /kafka/consumers/zoo-consumer-group/offsets/my-topic/0
    

转载于:https://my.oschina.net/liufukin/blog/3099744

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值