API文档
http://kafka.apache.org/10/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html.
版本说明
消费者API也分为新版和旧版
开发中都是直接使用新版本API:
org.apache.kafka.clients.consumer.KafkaConsumer
注意:
1.旧版:有两个级别的API:
-
低级/底层:可以手动维护offset
-
高级/高层:自动维护offset
http://kafka.apache.org/0100/documentation.html#impl_consumer.
2.新版:直接将旧版的低阶和高阶整合了,不再区分,可以手动维护offset也可以自动维护offset。
从哪个offset开始消费
1.旧版API:offset保存在ZK中,通过参数指定
- auto.offset.reset 的值为smallest:表示从分区的最小offset开始消费,类似与命令行消费时的 --from-beginning
- auto.offset.reset 的值为largest:表示从分区的最大offset开始消费,也就是从最新的数据开始消费,类似命令行消费时的 不加–from-beginning
2.新版API:offset存储在默认主题__consumer_offsets中,通过参数指定
- auto.offset.reset 的值为earliest :当各分区下有已提交的 Offset 时,从提交的 Offset开始消费;无提交的Offset 时,从最小/最早/最开始的数据开始消费;
- auto.offset.reset 的值为latest : 当各分区下有已提交的 Offset 时,从提交的 Offset 开始消费;无提交的 Offset时,从最大/最新/最后的数据开始消费
- auto.offset.reset 的值为none : Topic 各分区都存在已提交的 Offset 时,从 Offset 后开始消费;只要有一个分区不存在已提交的 Offset,则抛出异常。
如何提交偏移量
1.自动提交—一般都是用自动提交
- enable.auto.commit设置为true 表示自动提交(老版本提交到ZK,新版本提交到默认主题__consumer_offsets中)
- auto.commit.interval.ms设置一个自动提交offset的时间间隔
2.手动提交–对数据要求较高或想要精确控制时用手动提交!
-
enable.auto.commit设置为false表示需要手动提交偏移量
-
consumer.commitAsync();//异步提交
-
consumer.commitSync()//同步提交
导入Maven依赖
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
1.自动提交代码实现
- 使用KafkaConsumer 自动提交偏移量时,需要在配置属性中将“enable.auto.commit”设置为true , 另外可以设置“auto.commit.interval.ms" 属性来控制自动提交的时间间隔。
- Kafka 系统自动提交偏移量的底层实现调用了ConsumerCoordinator 的commitOffsetsSync()函数来进行同步提交,或者commitOffsetsAsync()函数来进行异步提交。自动提交的流程如图
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.util.Arrays;
import java.util.Properties;
/**
* 实现Kafka消费者自动提交偏移量
* kafka-console-producer.sh --broker-list node1:9092 --topic test_topic
*/
public class MyKafkaConsumer_Auto {
public static void main(String[] args) {
//TODO 1.准备参数
Properties props = new Properties();
//指定kafka集群地址
props.put("bootstrap.servers", "node1:9092,node2:9092,node3:9092");
// key的反序列化类
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
// value的序列化类
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//是否自动提交offset,true表示自动提交
props.put("enable.auto.commit", "true");
//自动确认提交偏移量offset的时间间隔
props.put("auto.commit.interval.ms", "1000");
//消费者组名称(如果不指定,会自动生成一个,但建议手动指定,方便管理)
props.put("group.id", "test_offset_auto");
//auto.offset.reset 的值更改为:earliest,latest,和none
//1.earliest :当各分区下有已提交的 Offset 时,从提交的 Offset开始消费;无提交的Offset 时,从头开始消费;
//2.latest : 当各分区下有已提交的 Offset 时,从提交的 Offset 开始消费;无提交的 Offset时,消费新产生的该分区下的数据
//3.none : Topic 各分区都存在已提交的 Offset 时,从 Offset 后开始消费;只要有一个分区不存在已提交的 Offset,则抛出异常。
props.put("auto.offset.reset", "latest");
//TODO 2.创建kafka消费者对象consumer
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String,String>(props);
//TODO 3.订阅的topic
kafkaConsumer.subscribe(Arrays.asList("order"));
//TODO 4.开始消费
while (true) {//消费者可以一直运行并且订阅主题消费其中的消息
//poll表示Kafka获得消息
//读取数据的延迟时间为100ms,每隔100ms去拉取数据
//如果为0,立即拉取数据,如果没有数据返回为空
//不能为负数
ConsumerRecords<String, String> Records = kafkaConsumer.poll(100);
for (ConsumerRecord<String, String> record : Records) {
System.out.println("消费到的数据,分区:"+record.partition()+" offset:"+record.offset()+" value:" + record.value());
}
}
}
}
2.手动提交代码实现
在编写消费者程序代码时,将配置属性“enable.auto.commit”的值设为“false”,则可以通过手动模式来提交偏移量。
Kafka Consumer 消费者程序类提供了两种手动提交偏移量的方式–同步提交commitSync()函数和异步提交commitAsync()函数。
同步提交和异步提交的区别在于:同步提交需要等待响应结果,会造成阻塞现象;异步提交不会被阻塞。
在实际应用场景中,会采用异步提交的方式来管理偏移量,这样有助于提升消费者程序的吞吐量。
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
* 实现Kafka消费者手动提交偏移量
*/
public class MyKafkaConsumer_ManualCommit {
public static void main(String[] args) {
//TODO 1.准备参数
Properties props = new Properties();
//kafka集群地址
props.put("bootstrap.servers", "node1:9092");//node1:9092,node2:9092,node3:9092
//消费者组名称(如果不指定,会自动生成一个,但一个都指定,方便管理)
props.put("group.id", "myGroup");
//是否自动提交offset,true表示自动提交,false表示使用手动提交
//如果需要手动管理offset,一定要注意,这个配置要给false
props.put("enable.auto.commit", "false");
//自动提交偏移量时的时间间隔ms值,手动提交时不需要指定时间间隔
//props.put("auto.commit.interval.ms", "1000");
//配置offset重置位置
//如果有offset记录就从记录的位置开始消费
//如果没有记录offset,earliest表示从最开始的数据,latest表示从最新的数据,none报错
props.put("auto.offset.reset", "earliest");
//反序列化kv类型
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//TODO 2.创建Kafka消费者对象
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(props);
//TODO 3.订阅主题
kafkaConsumer.subscribe(Arrays.asList("order"));
//TODO 4.开始消费
//手动提交:
//什么时候提交?
//--1.指定时间间隔,每隔xxms提交一次,这就和自动提交一样了,还不如直接使用自动提交!
//--2.每消费一条就提交一次!可以,但是可能会影响性能!
//--3.每消费一小批就提交一次,如:每消费5条就提交一次!
List<ConsumerRecord> list = new ArrayList<>();
while (true){//消费者可以一直运行并订阅主题消费其中的消息!
//poll表示从Kafka获得消息
ConsumerRecords<String, String> Records = kafkaConsumer.poll(100);
for (ConsumerRecord<String, String> record : Records) {
System.out.println("消费到的数据,分区:" + record.partition() + " offset:" + record.offset() + " value:" + record.value());
//kafkaConsumer.commitAsync();//每消费一条就提交一次
list.add(record);
if (list.size() >= 5) {
kafkaConsumer.commitSync();//每消费5条就提交一次!//同步
//kafkaConsumer.commitAsync();//每消费5条就提交一次!//异步
list.clear();
System.out.println("offset已提交");
}
}
}
}
}