Kafka 消费者手动提交 初体验

使用背景 : 

与第三方公司的一些基础数据对接,本来是通过定时器拉取数据. 但是项目多了 大了之后 发现偶合太高了. 故想使用中间件 来对这方面进行解耦. 但是不想消费的时候去自动提交, 因为代码中也有逻辑. 如果失败则需要继续消费失败的数据.

版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.2.5RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
    <version>2.3.6.RELEASE</version>
</dependency>

配置

spring:

  kafka:

    bootstrap-servers: ip:端口

    consumer:

      group-id: base_consumer_group #群组ID

      enable-auto-commit: false #取消自动提交

      max-poll-records: 10 #一次最大拉取消息数

      auto-offset-reset: earliest # 最早未被消费的offset

      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer

      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

      topics: topics_name_1,topics_name_2 # 监听的topics

编写Bean 为手动提交准备(我是写在启动类中的)

    /**
     * MANUAL   当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后, 手动调用Acknowledgment.acknowledge()后提交
     * @param consumerFactory
     * @return
     */
    @Bean("manualListenerContainerFactory")
    public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> manualListenerContainerFactory(
            ConsumerFactory<String, String> consumerFactory) {

        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory);
        factory.getContainerProperties().setPollTimeout(1500);
        factory.setBatchListener(true);

        //配置手动提交offset
        // 如果 ContainerProperties.AckMode 报错 请查看你的kafka 版本
        //如果想要使用其他模式 下面会列出来 请在此处替换即可
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL);
        return factory;
    }

各种提交模式

public enum AckMode {

		/**
		 * Commit after each record is processed by the listener.
		 */
		RECORD,

		/**
		 * Commit whatever has already been processed before the next poll.
		 */
		BATCH,

		/**
		 * Commit pending updates after
		 * {@link ContainerProperties#setAckTime(long) ackTime} has elapsed.
		 */
		TIME,

		/**
		 * Commit pending updates after
		 * {@link ContainerProperties#setAckCount(int) ackCount} has been
		 * exceeded.
		 */
		COUNT,

		/**
		 * Commit pending updates after
		 * {@link ContainerProperties#setAckCount(int) ackCount} has been
		 * exceeded or after {@link ContainerProperties#setAckTime(long)
		 * ackTime} has elapsed.
		 */
		COUNT_TIME,

		/**
		 * User takes responsibility for acks using an
		 * {@link AcknowledgingMessageListener}.
		 */
		MANUAL,

		/**
		 * User takes responsibility for acks using an
		 * {@link AcknowledgingMessageListener}. The consumer
		 * immediately processes the commit.
		 */
		MANUAL_IMMEDIATE,

	}
AckMode模式作用
MANUAL当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后, 手动调用Acknowledgment.acknowledge()后提交
MANUAL_IMMEDIATE手动调用Acknowledgment.acknowledge()后立即提交
RECORD当每一条记录被消费者监听器(ListenerConsumer)处理之后提交
BATCH当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后提交
TIME当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后,距离上次提交时间大于TIME时提交
COUNT当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后,被处理record数量大于等于COUNT时提交
COUNT_TIMETIME或COUNT 有一个条件满足时提交

具体代码简易实现

/**
  * topics 中 是读取配置 该写法可以监听多个topics
  * 如果不设置 manualListenerContainerFactory 下面的ack 会获取不到
  * 也可以改成配置的方式 则不需要写Bean 了 两种结果都是一样的
  * @param records
  * @param ack
  */
@KafkaListener(topics =  "#{'${spring.kafka.consumer.topics}'.split(',')}",containerFactory = "manualListenerContainerFactory")
public void listen(List<ConsumerRecord<String,String>> records, Acknowledgment ack) {
   try {
       //解析消息
        log.info("kafka成功,当前成功的批次。data:{}", records);
        for (ConsumerRecord record : records) {
            //处理消息
            log.info("处理消息 : {}", record);
        }
        //手动提交 至关重要
        ack.acknowledge();
   } catch (Exception e) {
        log.error("kafka失败,当前失败的批次。data:{}", records);
        e.printStackTrace();
        ack.nack(500);
   }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值