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();
...
}
代碼做了些簡略處理。明白思路就好做,然後就可以針對業務場景細化一下了。