版本依賴
1. spring-kafka: 2.2.2
2. kafka-clients: 2.0.0
使用示例
1. 構建監聽,acknowledgingMessageListener 爲接口org.springframework.kafka.listener.AcknowledgingMessageListener的實現類
ContainerProperties containerProps = new ContainerProperties(kafkaTopic); containerProps.setAckMode(ContainerProperties.AckMode.MANUAL); containerProps.setMessageListener(acknowledgingMessageListener);
2. 構建消費者
Map<String, Object> props = consumerProps(bootStrapServer, groupId, autoOffsetResetConfig); DefaultKafkaConsumerFactory<Integer, String> conf = new DefaultKafkaConsumerFactory<>(props); return new KafkaMessageListenerContainer<>(conf, containerProps);
DefaultKafkaConsumerFactory揭祕
protected KafkaConsumer<K, V> createKafkaConsumer(Map<String, Object> configs) { return new KafkaConsumer<>(configs, this.keyDeserializer, this.valueDeserializer); }
@Override public Consumer<K, V> createConsumer(@Nullable String groupId, @Nullable String clientIdPrefix, @Nullable String clientIdSuffix) { return createKafkaConsumer(groupId, clientIdPrefix, clientIdSuffix); }
KafkaMessageListenerContainer揭祕
class KafkaMessageListenerContainer<K, V> extends AbstractMessageListenerContainer<K, V>
abstract class AbstractMessageListenerContainer<K, V> implements GenericMessageListenerContainer<K, V>, BeanNameAware, ApplicationEventPublisherAware
interface GenericMessageListenerContainer<K, V> extends MessageListenerContainer
interface MessageListenerContainer extends SmartLifecycle
interface SmartLifecycle extends Lifecycle, Phased
啓動流程:
AbstractMessageListenerContainer.java#start() --> listener/AbstractMessageListenerContainer.java#doStart() --> this.listenerConsumer = new ListenerConsumer(listener, listenerType);
----> this.consumer = KafkaMessageListenerContainer.this.consumerFactory.createConsumer( this.consumerGroupId, this.containerProperties.getClientId(), KafkaMessageListenerContainer.this.clientIdSuffix); --------> while (isRunning()) { try { pollAndInvoke(); } ..... ..... } wrapUp(); }
this.fetcher = new Fetcher<>( logContext, this.client, config.getInt(ConsumerConfig.FETCH_MIN_BYTES_CONFIG), config.getInt(ConsumerConfig.FETCH_MAX_BYTES_CONFIG), config.getInt(ConsumerConfig.FETCH_MAX_WAIT_MS_CONFIG), config.getInt(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG), config.getInt(ConsumerConfig.MAX_POLL_RECORDS_CONFIG), config.getBoolean(ConsumerConfig.CHECK_CRCS_CONFIG), this.keyDeserializer, this.valueDeserializer, this.metadata, this.subscriptions, metrics, metricsRegistry.fetcherMetrics, this.time, this.retryBackoffMs, this.requestTimeoutMs, isolationLevel); ----> org/apache/kafka/clients/consumer/internals/Fetcher.java#fetchedRecords() --> int recordsRemaining = maxPollRecords; --> recordsRemaining -= records.size();
ConsumerRecords<K, V> records = this.consumer.poll(this.pollTimeout); KafkaConsumer.class#poll
KafkaMessageListenerContainer.java#invokeListener(records);
invokeRecordListenerInTx(records)
doInvokeRecordListener(record, producer, iterator);
invokeOnMessage(record, producer);
doInvokeOnMessage(record);
private void doInvokeOnMessage(final ConsumerRecord<K, V> record) { switch (this.listenerType) { case ACKNOWLEDGING_CONSUMER_AWARE: this.listener.onMessage(record, this.isAnyManualAck ? new ConsumerAcknowledgment(record) : null, this.consumer); break; case CONSUMER_AWARE: this.listener.onMessage(record, this.consumer); break; case ACKNOWLEDGING: this.listener.onMessage(record, this.isAnyManualAck ? new ConsumerAcknowledgment(record) : null); break; case SIMPLE: this.listener.onMessage(record); break; } }
至此,spring-kafka消費者的實現流程大致分析完成。