一、两种方式
1、构建多个KafkaConsumer进行消费,消费线程直接处理业务逻辑。
优势:代码实现简单,可采用自动提交
劣势:消费线程数和分区数挂钩,超过分区数的线程不做处理,扩展性差,线程自己处理消费到的消息可能会导致超时,从而造成rebalance
2、构建一个或多个KafkaConsumer实例,每个实例采用worker线程池处理业务逻辑。
优势:消费逻辑和业务逻辑分离,易于横向扩展
劣势:实现较麻烦,难于维护分区内的消息顺序,处理链路变长,导致难以保证提交位移的语义正确性
二、具体代码实现
1、方式一
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
@Slf4j
public class KafkaConsumerClient {
private Boolean isRunning;
private ExecutorService executor;
private String servers;
private int sessionTimeout;
private int maxPollSize;
private String groupId;
private String topic;
private int parallelism;
public KafkaConsumerClient(String servers, int sessionTimeout, int maxPollSize,
String groupId, String topic,
boolean isRunning) {
this.servers = servers;
this.sessionTimeout = sessionTimeout;
this.maxPollSize = maxPollSize;
this.groupId = groupId;
this.topic = topic;
this.isRunning = isRunning;
}
public KafkaConsumerClient(String servers, String groupId, String topic,
boolean isRunning) {
this(servers, 30000, 100, groupId, topic, isRunning);
}
public KafkaConsumerClient() {
}
public void init(){
if(isRunning){
start(parallelism);
log.info("the kafka consume client has start!");
}
}
public void start(int parallelism) {
if(parallelism > 0){
isRunning = true;
this.parallelism = parallelism;
executor = Executors.newFixedThreadPool(parallelism);
IntStream.range(0, parallelism).forEach(i -> {
executor.submit(new ConsumerRunner("kafka-client-consumer-" + i));
});
}else{
this.parallelism = 0;
}
}
public void stop(){
isRunning = false;
this.parallelism = 0;
if(executor != null){
executor.shutdown();
try {
if(!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
log.info("kafka client has stopped!");
}
} catch (InterruptedException e) {
executor.shutdownNow();
log.error("kafka client has stopped! ", e);
}
}
}
class C