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
		**/

	}

posted @ 2024-09-03 17:12  cqzaier  阅读(20)  评论(0)    收藏  举报