与KafkaProduer类似,只是初始化的组件有所差异,看KafkaConsumer构造函数
ConsumerConfig:消费者级别的配置,将相应配置传递给其他组件
ConsumerCoodinator:负责消费者与服务端 GroupCoordinator 通信
ConsumerNetworkClient:对网络层通信 NetworkClient 的封装,用于消费者与服务端的通信
Fetcher:对 ConsumerNetworkClient 进行了包装,负责从服务端获取消息
SubscriptionState:维护了消费者订阅和消费消息的情况,保存订阅信息的字段,其中主要属性如下,
2种订阅topic的方式:
1种是通过subscribe方法指定消息对应的主题,支持以正则表达式方式指定主题
1种是assign方法指定需要消费的分区
ps:使用正在表达式方式,会定期检测topic,当topic数量或topic分区数量发生变化时,会将该topic在消费者组订阅的topic列表种删除,然后进行再平衡操作;需要注意的是,这两种订阅topic的方式是互斥的,在客户端只能选择其中一种
KafkaComsumer的poll方法用于从服务器拉取消息,可指定等待时长timeout,若timeout=0,则在没有拉取到消息时无需等待重试直接返回客户端;否则在timeout时间内进行重试直到取到消息or在等待超过timeout时间后构造响应结果返回客户端;真正拉取消息是通过Fetcher类构造拉取消息的FetchRequest 请求,然后通过ConsumerNetworkClient发送FetchRequest请求,最后对返回的结果进行处理并更新缓存中记录的消费位置
a.Api方式:
https://blog.csdn.net/lishuangzhe7047/article/details/74530417
b.自动设置消费起始位置:
通过auto.offset.reset配置项设置消费起始位置,默认值为LATEST;在 KafkaConsumer 初始化时会读取配置项 auto.offset.reset 配置的消费位置重置策略初始化SubscriptionState;在 pollOnce()方法在执行时会检测是否订阅的主题和分区都已设置了消费起始位置,即订阅列表对应的Topic PartitionState.position不为空,若订阅列表中存在TopicPartitonState.position为空,则先通过Fetcher 根据自动重置策略获取消费起始位置,若仍有部分订阅分区没有获取到消费起始位置,则通过 Fetcher 向 Kafka 集群发送 OffsetFetchRequest 请求,请求获取消费起始位置
旧版消费者保存在zookeeper的/consumers/${group.id}/offsets/${topicName}/${partitionId}节点中
新版消费者保存到Kafka一个内部主题”__consumer_offsets”中,该topic总保留各分区被消费的最新偏移量,消费偏移量如同普通消息一样追加到该主题相应的分区当中,根据算法(Math.abs(${group.id}.hashCode()%${offsets.topic.num.partitions}来确定消费偏移量提交的分区(offsets.topic.num.partitions指的是__consumer_offsets这个topic的分区数,可配置,默认50)
格式为:key=group.id,topic,partition value=offset,metadata,timestamp
a.api手动提交方式(enable.auto.commit需置为false):
commitSync方法:同步提交
commitAsync()方法:异步提交
都是通过ConsumerCoordinator发送偏移量消息追加到Kafka内部主题当中
同步与异步的区别:同步提交时,KafkaConsumer 在提交请求响应结果返回前会一直被阻塞,在成功提交后才会进行下一次拉取消息操作;异步提交时KafkaConsumer不会被阻塞,但当提交发生异常时就有可能发生重复消费的问题,但异步方式会提高消费吞吐量(如:提交不成功时候消费者线程出异常挂了,下一次消费者起来便会重复消费数据)
b.自动提交方式(enable.auto.commit需置为true): 可通过配置项auto.commit.interval.ms来设置提交操作的时间间隔,自动提交并非通过定时任务周期性地提交,而是在一些特定事件发生时才检测与上一次提交的时间间隔是否超过了${auto.commit.interval.ms}计算出的下一次提交的截止时间nextAutoCommitDeadline,若时间间隔超过了nextAutoCommitDeadline 则请求提交偏移量,同时更新下一次提交消费偏移量的nextAutoCommitDeadline
特定事件如下:
可通过配置项partition.assignment.strategy来设置消费者线程与分区映射关系,有如下2种配置
range 分配策略:默认值,按照线程总数与分区总数进行整除运算计算一个跨度,然后将分区按跨度进行平均分配,以保证分区尽可能均衡地分配给所有消费者线程(对应RangeAssignor类),举例如下:
round-robin 分配策略:将订阅的主题分区以及消费者线程进行排序,然后通过轮询方式逐个将分区依次分给消费者线程(对应RoundRobinAssignor类),举例如下:
range策略总结:
Pnt 表示分区总数,Cnt 表示消费者线程总数:
range策略订阅多个主题分配过程与单个主题类似,多个主题分配拆分为多次单个主题分配即可,举例如下:
发生消费者平衡过程的情况:
a.新的消费者加入消费组
b.当前消费者从消费组退出(这里的退出包括异常退出和消费者正常关闭 )
c.消费者取消对某个主题的订阅
d.订阅主题的分区增加
e.代理宕机新的协调器当选
f.当消费者在${session.timeout.ms}毫秒内还没发送心跳请求,组协调器认为消费者已退出
作用:用于对consumer group进行的管理,管理消费者偏移量、执行rebalance
老版本coordinator(0.9以前):依赖zookeeper来发挥作用,监听zookeeper的节点变化来管理偏移量与执行rebalance
新版本coordinator(0.9开始):不依赖zookeeper,为每个consumer group分配一个coordinator,consumer group内的成员与该coordinator进行协调通信来完成偏移量管理与rebalance
consumer group如何确定coordinator:
a.确定位移信息写入__consumers_offsets的哪个分区,公式如下:(Math.abs(${group.id}.hashCode()%${offsets.topic.num.partitions}来确定消费偏移量提交的分区(offsets.topic.num.partitions指的是__consumer_offsets这个topic的分区数,可配置,默认50)
b.该分区leader所在的broker就是被选定的coordinator
rebalance概念介绍:
Rebalance Generation:相当于JVM GC的分代,表示了rebalance之后的一届成员,用于保护consumer group,隔离无效的offset提交(如:上一届的consumer成员是无法提交位移到新一届的consumer group中),每次group进行rebalance之后,generation号都会加1,表示group进入到了一个新的版本
rebalance协议:
1.创建一个topic为mytest
2.创建消费者订阅mytest 的topic,所属consumer group为test-kafka-offset
3.启动消费者消费数据(由于只有1个消费者,故同时消费4分区),消费者每5s会提交一次offset即使没数据消费 kafka-console-consumer.sh --bootstrap-server kafka-ip:port --group test-kafka-offset --topic mytest
4.计算该consumer group的offset在__consumer_offsets中的分区
5.Math.abs("test-kafka-offset".hashCode()) % 50=15
6.起个消费者订阅__consumer_offsets,可以看到该test-kafka-offset里面consumer的消费情况如下
查看命令:
kafka-console-consumer.sh --topic __consumer_offsets --partition 15 --bootstrap-server kafka-ip:port --formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter"
7.创建一个生产者往mytest中塞4条数据
kafka-console-producer.sh --broker-list kafka-ip:port --topic mytest
8.再查看__consumer_offsets中test-kafka-offset的消费情况如下
9.不断生产数据会发现偏移量不断发生变化
1.新成员加入consumer group:
2.consumer group成员崩溃:
3.consumer group成员主动离组:
4.提交消费偏移量:
ps:以上几张图是引用别的博客的,本应附上博客的地址,但是之前没保存现在一直找不到那篇博客,以后有缘遇到补上~