概述
KafkaConsumer是从Kafka服务端拉取消息的API,开发人员可以基于这套API轻松实现从Kafka服务端拉取消息的功能; 消费者是如何与Kafka服务端之间实现网络连接的管理、心跳检测、请求超时重试等功能 消费者是如何实现订阅Topic的分区数量、以及Consumer Group的重平衡、自动提交offset的功能。
我们从的三部分介绍KafkaConsumer的源码:
- 消费者初始化(本文介绍)
- 消费者如何拉取的数据的
- 消费者是如何与协调者(ConsumerCoordinator)交互的
来分析上面的问题
名词解释
消费组:消费者组是一组消费者,它们合作消费来自某些主题的数据 offset:位移,Kafka服务端并不会记录消费者的消费位置, 而是由消费者自己决定如何保存如何记录其消费的offset。旧版本的消费者会将其消费位置记录到Zookeeper中,在新版本消贵者中为了缓解Zookeeper集群的压力,在Kafka服务端中添加了一个名为“consumer offsets”的内部Topic 分区重新分配:当消费者上下线都会触发消费组进行重平衡操作,对分区进行重新分配,待重平衡操作完后,消费者就可以读取offserts topic中的记录的offset,并从offset位置继续消费。
代码入口
public Consumer(final String topic,
final String groupId,
final Optional<String> instanceId,
final boolean readCommitted,
final int numMessageToConsume,
final CountDownLatch latch) {
this.groupId = groupId;
Properties props = new Properties();
// 服务器地址和端口
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KafkaProperties.KAFKA_SERVER_URL + ":" + KafkaProperties.KAFKA_SERVER_PORT);
// 消费组id
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
instanceId.ifPresent(id -> props.put(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG, id));
// 自动提交偏移量,每次在调用KafkaConsumer.poll 方法时都会检测是否需要自动提交,并提交上次poll方法返回的最后 一个消息的offset
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
// 序列化
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
if (readCommitted) {
props.put(ConsumerConfig.ISOLATION_LEVEL_CONFIG, "read_committed");
}
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
// 重点1 这次重点分析这块 创建一个 KafkaConsumer 对象,这个对象负责与Kafka集群进行通信。
配置 KafkaConsumer 对象,包括指定Kafka集群的地址、消费者组ID、序列化器和反序列化器等参数。
consumer = new KafkaConsumer<>(props);
}
public void run() {
try {
// 订阅一个或多个主题,通过调用 KafkaConsumer.subscribe() 方法并指定需要订阅的主题名称列表来实现。这个方法会发送一次订阅请求到Kafka集群,Kafka会返回订阅成功的主题列表。
consumer.subscribe(Collections.singletonList(this.topic), this);
// 开始拉取数据。这个方法会向Kafka集群发送拉取请求,然后等待Kafka返回数据。返回的数据将被存储在内存中的缓冲区中,等待消费者处理。
ConsumerRecords<Integer, String> records = consumer.poll(Duration.ofSeconds(1));
} catch (Exception e) {
//
} finally {
//shutdown();
}
}
复制代码
- 说明
- 消费者的参数配置: