kafka定时任务拉取数据

1  定时任务两种, 2 消费分组消费从哪里开始,不消费历史数据  

  定时主要是为了延迟拉消费,最简单方式  直接批量拉取之后, ack批量提交后, 线程挂起3秒,更好达到效果

  if (kafuKfaUtils.insertFlowdata(jsonarray, map)) {
                    ack.acknowledge();
                }
提交之后, 再等待几秒,以拉取更多数据    
    
    long start = System.currentTimeMillis();
            System.out.println("线程挂起2秒" + start);
            Thread.sleep(2000);//睡眠5秒
            long end = System.currentTimeMillis();
            System.out.println("线程恢复" + (end - start) / 1000);

第一种监听的方式定时

springboot1.5.6 + kafka2.1.7 依赖包  包冲突后,  又改回springboot-kafka1.1.1  定时任务不理想,恢复和暂停有问题

      <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>2.1.7.RELEASE</version>
        </dependency>

注入实例  当执行完成后, 取消监听topic  定时开启监控,这个在KAFKA之前的版本并不支持 监听和取消 ,我升级包后才行

后面主要是逻辑代码了, 后面贴上  

@KafkaListener(id = "flow-task", topics = "topic_collect", group = "flow-topic", containerFactory = "batchFlowFactory")  低版本没有groupId 兼容问题,暂停会有问题,
@Service
public class KafkaTaskService {
    private static final Logger log = LoggerFactory.getLogger(KafkaTaskService.class);
    @Autowired
    private              KafkaListenerEndpointRegistry registry;

    /**
     * 定时执行
     *
     * @param recordList
     * @param acknowledgment
     */
    @KafkaListener(id = "flow-task", topics = "topic_collect", group = "flow-topic", containerFactory = "batchFlowFactory")
    public void listenFailEmail(List<ConsumerRecord> recordList, Acknowledgment acknowledgment) {
        System.out.println(recordList.size() + "条数据,监听消费开始");
        for (ConsumerRecord record : recordList) {
            log.info("fail email-消息:【{}】。", record.value().toString());
        }
        acknowledgment.acknowledge();
        shutdownListener();
        System.out.println("********* 监听消费结束");
    }

    @Scheduled(cron = "0/20 * * * * ?")
    public void startListener() {
        log.info("开启监听");
        MessageListenerContainer container = registry.getListenerContainer("flow-task");
        if (!container.isRunning()) {
            container.start();
            System.out.println("开启监听");
        }
        //恢复
        //  container.resume();
    }

    //@Scheduled(cron = "0 08 12 * * ?")  //12点08分执行
    public void shutdownListener() {
        //  log.info("关闭监听");
        //暂停
        MessageListenerContainer container = registry.getListenerContainer("flow-task");
        container.stop();
        System.out.println("关闭监听");
        //  conta

    /**
     * kafka监听工厂
     *
     * @param configurer
     * @return
     */
    @Bean("batchFactory")
    public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(
            ConcurrentKafkaListenerContainerFactoryConfigurer configurer,
            ConsumerFactory consumerFactory) {
        ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory);
        //开启批量消费功能
        factory.setBatchListener(true);
        //不自动启动
        factory.setAutoStartup(false);
        configurer.configure(factory, consumerFactory);
        return factory;
    }
}

 

定时任务第二种方式

通过实践获取一下结论:

1.topic可以被多个group消费
group之间消费位移互不干扰
2.topic被group消费时,若有多个消费者实例,同一条消息只会被一个消费者处理
3.一个group可以消费多个topic
4.一个消费者group可以拉取多个topic消息

代码如下 核心代码  加入新分组可以定时拉任务, 但结果不是自己想要的,一分钟拉一次,数据处理不完的时候,会怎么样

@EnableAsync
@Component
public class GroupQueue {
    static boolean RUN = false;

    @Async
    @Scheduled(cron = "0 * * * * ?")
    public void task() {
        if (RUN) {
            return;
        }
        RUN = true;
        KafkaConsumer consumer = KafkaConsumerFactory.getKafkaConsumer("group2");
        consumer.subscribe(Arrays.asList("GroupQueue", "FriendQueue"));

        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(100);
            System.out.println("批次:" + UUID.randomUUID().toString());

            for (ConsumerRecord<String, String> record : records) {
                System.out.printf(record.topic() +
                    "一条新消息 offset = %d, key = %s, value = %s", record.offset(),
                    record.key(), record.value());
                System.out.println(record.topic() + "partition:" +
                    record.partition());

                // 业务处理 TODO
            }

            // 同步提交
            if (records.count() > 0) {
                consumer.commitSync();
                System.out.println("批次提交");
            }
        }
    }

    public static KafkaConsumer getKafkaConsumer(String group) {
        Properties propstask = new Properties();
        propstask.put("bootstrap.servers", "107.101.117.118:9092 107.101.117.119:9092 107.101.117.117:9092");
        //每个消费者分配独立的组号
        propstask.put("group.id", group);
        //如果value合法,则自动提交偏移量
        propstask.put("enable.auto.commit", "false");
        // 每次拉取5000条
        propstask.put("max.poll.records", 10000);
        //设置多久一次更新被消费消息的偏移量
        propstask.put("auto.commit.interval.ms", "1000");
        //设置会话响应的时间,超过这个时间kafka可以选择放弃消费或者消费下一条消息
        propstask.put("session.timeout.ms", "30000");
        //自动重置offset
        propstask.put("auto.offset.reset", "latest");//latest  earliest
        propstask.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        propstask.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        return new KafkaConsumer<String, String>(propstask);
    }

}

不消费历史数据,添加分组消费最新数据,放弃消费历史数据等

设置消费者properties的两个参数

consumer.group.id

properties.setProperty("auto.offset.reset", "earliest”) // latest

注意:

只要不更改group.id,每次重新消费kafka,都是从上次消费结束的地方继续开始,不论"auto.offset.reset”属性设置的是什么

 

场景一:Kafka上在实时被灌入数据,但kafka上已经积累了两天的数据,如何从最新的offset开始消费?

(最新指相对于当前系统时间最新)

1.将group.id换成新的名字(相当于加入新的消费组)

 

2.网上文章写还要设置 properties.setProperty("auto.offset.reset", "latest”)

实验发现即使不设置这个,只要group.id是全新的,就会从最新的的offset开始消费

 

场景二:kafka在实时在灌入数据,kafka上已经积累了两天的数据,如何从两天前最开始的位置消费?

1.将group.id换成新的名字

2.properties.setProperty("auto.offset.reset", "earliest”)

 

场景三:不更改group.id,只是添加了properties.setProperty("auto.offset.reset", "earliest”),consumer会从两天前最开始的位置消费吗?

不会,只要不更改消费组,只会从上次消费结束的地方继续消费

 

场景四:不更改group.id,只是添加了properties.setProperty("auto.offset.reset", "latest”),consumer会从距离现在最近的位置消费吗?

不会,只要不更改消费组,只会从上次消费结束的地方继续消费

 

应用:

正式打包上线前应该使用新的group.id,以便于从kafka最新的位置开始消费

只要将group.id换成全新的,不论"auto.offset.reset”是否设置,设置成什么,都会从最新的位置开始消费

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值