本文涉及到的所有代码详见Github
上手Kafka Consumer是比较容易的,这里以原生的Java API为例,通常的实现逻辑如下所示:
public void consumer() {
String brokers = "localhost:9092";
String group = "group_test";
String topic = "topic_demo";
Properties props = new Properties();
props.put("bootstrap.servers", brokers);
props.put("group.id", group);
props.put("enable.auto.commit", "true");
props.put("auto.offset.reset", "latest");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList(topic));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records) {
System.out.println(record.toString());
}
}
}
对应的maven依赖为
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.0.1</version>
</dependency>
可以看到通过配置一些参数,并调用poll方法就可以开始消费消息。如果想要了解Consumer的实现原理,当然绕不开阅读poll方法的源码,本篇先抛开poll的实现原理,可以先简单的理解为:调用poll方法可以实现将Client加入到Group中,获取Partition信息,并且拉去对应Partition上的数据。接下来首先会对Consumer的几个主要的参数做以说明,然后通过几个案例来加深对Consumer的使用。在案例的实现过程中涉及到有过Kafka底层的相关知识,若有不清楚的可先阅读 Partition & Replication、Consumer-Group-Coordinator 。
poll()源码的分析可参考poll模型
参数解析
client.id
用来指定当前客户端的标识符名称,不同的客户端API会有与之对应的命名规则;例如原生的Java API中client.id的命名规则是以“consumer-”为前缀,后跟自增长Id;在Kafka-Python中,client.id的命名规则为“kafka-python-” + Kafka-Python版本号。通常是不需要业务代码里显示的指定,但是在特定场景下,可以根据client.id来改变Partition的分配结果,从而实现特殊的需求。
session.timeout.ms
在无心跳时,broker判定Consumer Client存活的最大时间间隔;即就是在此时间范围内,如果客户端不发送心跳,Coordinator也会认为该Client依旧是存活的;一旦超过该时间Coordinator仍未收到心跳,则Broker会移除该Consumer Client并主动触发Rebalance;默认时长为3000(3s)。
在实际应用中,必须斟酌在真实业务场景中消息处理的实际耗时与session.timeout.ms的大小,否则会出现因为处理超时导致在offset还未提交时Coordinator主动触发了Group的Rebalanc