Kafka 消費時機問題

kafka的消費時機

問題

kafka啓動後開始消費的話, 如果此時消費流程中有其他依賴沒有啓動完成的話,比如 Redis , Mysql ,RPC等就會有空指針或其他問題。這時候就要延後kafka的消費時機。

解決

kafka啓動時,不在啓動時開啓消費線程。

public class KafkaConsumer {

private KafkaConsumer<String, byte[]> consumer;
private ThreadPoolExecutor threadPoolExecutor;
private ThreadPoolExecutor threadConsumerExecutor;


public void init(String kafkaTopic, String groupIdConfig) {
    //init pool
    //init consumer
    。。。。。
}

//開始消費單獨拿出方法
public void startConsumer(final Handler handler) {
    threadConsumerExecutor.submit(new Runnable() {
        @Override
        public void run() {
            while(true){
                ConsumerRecords<String, byte[]> data = consumer.poll(200);
                .....
                handler.onMessage(data)
                sleep(100)
            }
            
        }
    });
}

然後在SpringBoot啓動後,再啓用kafka的消費線程

@Component
public class ApplicationRunnerImpl implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //校驗Redis
        //校驗Mysql
        //校驗RPC
        kafkaConsumer.start()
    }
}

此時啓用kafkaConsumer,就不會有問題了。

升級版

可以設置標誌位,來靈活做到啓/停/暫停/恢復

public class KafkaConsumer {
    //標識位,是否開始消費線程
private AtomicBoolean polling = new AtomicBoolean(true);
private KafkaConsumer<String, byte[]> consumer;
private ThreadPoolExecutor threadPoolExecutor;
private ThreadPoolExecutor threadConsumerExecutor;
private Handler handler;


public void init(String kafkaTopic, String groupIdConfig) {
    //init pool
    //init consumer
    。。。。。
    startConsumer()
}

//開始消費單獨拿出方法
public void startConsumer() {
    threadConsumerExecutor.submit(new Runnable() {
        @Override
        public void run() {
            while(this.polling.get()){
                ConsumerRecords<String, byte[]> data = consumer.poll(200);
                .....
                handler.onMessage(data)
                sleep(100)
            }
        }
    });
}
//暫停消費線程
public void pause(){
    this.polling.set(false)
}

//恢復消費線程
public void resume(){
    this.polling.set(true)
}

//關閉消費
public void shutDown(){
    pause();
    unsubscribe();
    threadConsumerExecutor.shutdown();
    ...

}

代碼做了些簡略處理。明白思路就好做,然後就可以針對業務場景細化一下了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章