springboot-Kafka源码—消费者
@KafkaListener 注解的实现
KafkaListenerAnnotationBeanPostProcessor
org.springframework.kafka.annotation.KafkaListenerAnnotationBeanPostProcessor#processListener
// KafkaListenerEndpointRegistrar registrar = new KafkaListenerEndpointRegistrar();
this.registrar.registerEndpoint(endpoint, listenerContainerFactory);
//KafkaListenerEndpointDescriptor
KafkaListenerEndpointDescriptor descriptor = new KafkaListenerEndpointDescriptor(endpoint, factory);
synchronized (this.endpointDescriptors) {
if (this.startImmediately) { // Register and start immediately
this.endpointRegistry.registerListenerContainer(descriptor.endpoint,
resolveContainerFactory(descriptor), true);
}
else {
this.endpointDescriptors.add(descriptor);
}
}
具体注册监听容器的bean KafkaListenerEndpointRegistrar
org.springframework.kafka.config.KafkaListenerEndpointRegistrar#registerAllEndpoints
this.endpointRegistry.registerListenerContainer(
descriptor.endpoint, resolveContainerFactory(descriptor));
// descriptor 就是消费者的信息
descriptor 里面包含了bean对象和方法
注册监听容器 MessageListenerContainer接口
org.springframework.kafka.config.KafkaListenerEndpointRegistry#registerListenerContainer
ConcurrentMessageListenerContainer
org.springframework.kafka.listener.ConcurrentMessageListenerContainer#doStart
KafkaMessageListenerContainer
//org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter 反射执行对象 onMessage
Object messageListener = containerProperties.getMessageListener();
//consumerExecutor ==> org.springframework.core.task.SimpleAsyncTaskExecutor【核心】
//org.springframework.kafka.listener.KafkaMessageListenerContainer.ListenerConsumer#run
this.listenerConsumerFuture = consumerExecutor
.submitListenable(this.listenerConsumer);
// 超时
this.startLatch = new CountDownLatch(1);
if (!this.startLatch.await(containerProperties.getConsumerStartTimeout().toMillis(), TimeUnit.MILLISECONDS)) {
this.logger.error("Consumer thread failed to start - does the configured task executor "
+ "have enough threads to support all containers and concurrency?");
publishConsumerFailedToStart();
}
消费者拉去消息的方法
org.springframework.kafka.listener.KafkaMessageListenerContainer.ListenerConsumer#run
while (isRunning()) {
try {
pollAndInvoke();
}
catch (@SuppressWarnings(UNUSED) WakeupException e) {
............
catch (Exception e) {
handleConsumerException(e);
}
}
wrapUp(exitThrowable);
拉取消息
private ConsumerRecords<K, V> doPoll() {
ConsumerRecords<K, V> records;
if (this.isBatchListener && this.subBatchPerPartition) {
if (this.batchIterator == null) {
this.lastBatch = this.consumer.poll(this.pollTimeout);
if (this.lastBatch.count() == 0) {
return this.lastBatch;
}
else {
this.batchIterator = this.lastBatch.partitions().iterator();
}
}
TopicPartition next = this.batchIterator.next();
List<ConsumerRecord<K, V>> subBatch = this.lastBatch.records(next);
records = new ConsumerRecords<>(Collections.singletonMap(next, subBatch));
if (!this.batchIterator.hasNext()) {
this.batchIterator = null;
}
}
else {
records = this.consumer.poll(this.pollTimeout);
checkRebalanceCommits();
}
return records;
}
org.springframework.kafka.listener.KafkaMessageListenerContainer.ListenerConsumer#invokeOnMessage 调用反射
ConsumerRecords<K, V> records = doPoll();
invokeIfHaveRecords(records);
org.springframework.kafka.listener.KafkaMessageListenerContainer.ListenerConsumer#invokeOnMessage
spring的扩展点——SmartLifecycle
执行到doStart方法 SmartLifecycle用法
protected void finishRefresh() {
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
/**
org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
**/
}