kafka消费者客户端再平衡表示的是分区的所属权从一个消费者转移到了另一个消费者的行为,它为消费者组具备高可用性和伸缩性提供保障,使我们能够方便的删除消费者组中的消费者或者往消费者组中添加消费者。但是在再平衡期间,消费者组内的消费者是无法读取消息的,在再均衡这一段时间内,消费者组不可用。
再均衡可能会导致向消费者位移还未来得及提交就发生了再均衡操作,会导致消息重复。
在消费者订阅主题的时候除了subscribe(Collection<String> topics)
还提供了public void subscribe(Pattern pattern, ConsumerRebalanceListener listener)
。
ConsumerRebalanceListener
提供了两个方法:
void onPartitionsRevoked(Collection<TopicPartition> partitions);
这个方法会在再平衡开始之前和消费者停止读取消息之后被调用,可以在此处将位移提交。这里的partitions表示的是再平衡之前的分区
void onPartitionsAssigned(Collection<TopicPartition> partitions);
这个方法在重新分配分区之后和开始消费消息之前被调用,partitions表示的是在平衡后分配的分区
示例代码:
/**
* 消费者再平衡
*/
public class ConsumerRebalance {
public static final String brokerList = "10.201.83.207:9092,10.202.82.49:9092,10.202.43.113:9092";
public static final String topic = "test-001";
public static final String groupId = "consumer_001_test";
public static Properties initConfig() {
Properties properties = new Properties();
properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerList);
properties.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
properties.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
properties.setProperty(ConsumerConfig.CLIENT_ID_CONFIG, "consumer-test-001");
properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG,groupId);
return properties;
}
public static void main(String[] args) throws Exception{
Properties props = initConfig();
KafkaConsumer<String,String> consumer = new KafkaConsumer<String, String>(props);
consumer.subscribe(Arrays.asList(topic), new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
consumer.commitSync();
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
}
});
while(true){
ConsumerRecords<String,String> records = consumer.poll(1000);
for(ConsumerRecord<String,String> record:records){
System.out.println("topic="+record.topic()+",partition="+record.partition()
+",offset="+record.offset()+",key="+record.key()+",value="+record.value());
}
}
}
}