kafka 主动消费_Kafka核心API——Consumer消费者

Consumer之自动提交

在上文中介绍了Producer API的使用,现在我们已经知道如何将消息通过API发送到Kafka中了,那么现在的生产者/消费者模型就还差一位扮演消费者的角色了。因此,本文将介绍Consumer API的使用,使用API从Kafka中消费消息,让应用成为一个消费者角色。

还是老样子,首先我们得创建一个Consumer实例,并指定相关配置项,有了这个实例对象后我们才能进行其他的操作。代码示例:

/**

* 创建Consumer实例

*/

public static Consumer createConsumer() {

Properties props = new Properties();

// 指定Kafka服务的ip地址及端口

props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "127。0.0.1:9092");

// 指定group.id,Kafka中的消费者需要在消费者组里

props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "test");

// 是否开启自动提交

props.setProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");

// 自动提交的间隔,单位毫秒

props.setProperty(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");

// 消息key的序列化器

props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,

"org.apache.kafka.common.serialization.StringDeserializer");

// 消息value的序列化器

props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,

"org.apache.kafka.common.serialization.StringDeserializer");

return new KafkaConsumer<>(props);

}

在以上代码中,可以看到设置了group.id这个配置项,这是一个Consumer的必要配置项,因为在Kafka中,Consumer需要位于一个Consumer Group里。具体如下图所示:

在上图中是一个Consumer消费一个Partition,是一对一的关系。但Consumer Group里可以只有一个Consumer,此时该Consumer可以消费多个Partition,是一对多的关系。如下图所示:

一个Consumer可以只消费一个Partition,也可以消费多个Partition,但需要注意的是多个Consumer不能消费同一个Partition:

总结一下Consumer的注意事项:

单个Partition的消息只能由Consumer Group中的某个Consumer来消费

Consumer从Partition中消费消息是顺序的,默认从头开始消费

如果Consumer Group中只有一个Consumer,那么这个Consumer会消费所有Partition中的消息

在Kafka中,当消费者消费数据后,需要提交数据的offset来告知服务端成功消费了哪些数据。然后服务端就会移动数据的offset,下一次消费的时候就是从移动后的offset位置开始消费。

这样可以在一定程度上保证数据是被消费成功的,并且由于数据不会被删除,而只是移动数据的offset,这也保证了数据不易丢失。若消费者处理数据失败时,只要不提交相应的offset,就可以在下一次重新进行消费。

和数据库的事务一样,Kafka消费者提交offset的方式也有两种,分别是自动提交和手动提交。在本例中演示的是自动提交,这也是消费数据最简单的方式。代码示例:

/**

* 演示自动提交offset

*/

public static void autoCommitOffset() {

Consumer consumer = createConsumer();

List topics = List.of("MyTopic");

// 订阅一个或多个Topic

consumer.subscribe(topics);

while (true) {

// 从Topic中拉取数据,每1000毫秒拉取一次

ConsumerRecords records = consumer.poll(Duration.ofMillis(1000));

// 每次拉取可能都是一组数据,需要遍历出来

for (ConsumerRecord record : records) {

System.out.printf("partition = %d, offset = %d, key = %s, value = %s%n",

record.partition(), record.offset(), record.key(), record.value());

}

}

}

Consumer之手动提交

自动提交的方式是最简单的,但不建议在实际生产中使用,因为可控性不高。所以更多时候我们使用的是手动提交,但想要使用手动提交,就需要先关闭自动提交,修改配置项如下:

props.setProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");

关闭了自动提交后,就得在代码中调用commit相关的方法来提交offset,主要就是两个方法:commitAsync和commitSync,看方法名也知道一个是异步提交一个是同步提交。

这里以commitAsync为例,实现思路主要是在发生异常的时候不要调用commitAsync方法,而在正常执行完毕后才调用commitAsync方法。代码示例:

/**

* 演示手动提交offset

*/

public static void manualCommitOffset() {

Consumer consumer = createConsumer();

List topics = List.of("MyTopic");

// 订阅一个或多个Topic

consumer.subscribe(topics);

while (true) {

// 从Topic中拉取数据,每1000毫秒拉取一次

ConsumerRecords records = consumer.poll(Duration.ofMillis(1000));

// 每次拉取可能都是一组数据,需要遍历出来

for (ConsumerRecord record : records) {

try {

// 模拟将数据写入数据库

Thread.sleep(1000);

System.out.println("

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值