kafka源码分析之consumer的源码

本文深入探讨了Kafka Consumer的客户端实现,包括如何创建KafkaConsumer实例、订阅主题、读取消息以及消费者组协调。详细分析了配置参数、网络客户端、元数据管理和心跳机制,展示了Consumer如何处理分配、重试、心跳与offset提交等核心功能。
摘要由CSDN通过智能技术生成

Consumerclient

示例代码

Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG"localhost:9092");
props.put(ConsumerConfig.GROUP_ID_CONFIG"DemoConsumer");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG"false");
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG"30000");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG

        "org.apache.kafka.common.serialization.ByteArrayDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG

        "org.apache.kafka.common.serialization.ByteArrayDeserializer");

 

 

consumer = new KafkaConsumer<>(props);
this.topic = topic;

 

consumer.subscribe(Collections.singletonList(this.topic));

//下面的传入一个listener这个部分的注释如果需要对partition在当前的consumer中分配或者取消分配时做一定的操作时(比如取消分配时提交offset),可以实现这个接口。

//subscribe(List<String> topicsConsumerRebalanceListener listener)

while(true) {
   ConsumerRecords<IntegerString> records = consumer.poll(1000);
   for (ConsumerRecord<IntegerString> record : records) {
     System.out.println("Received message: (" + record.key() + ", " + record.value() 

         + ") at offset " + record.offset());

      
   }

 

   consumer.commitSync()

}

 

生成KafkaConsumer实例


@SuppressWarnings("unchecked")
private KafkaConsumer(ConsumerConfig config,
                      Deserializer<K> keyDeserializer,
                      Deserializer<V> valueDeserializer) {
    try {
        log.debug("Starting the Kafka consumer");

 

根据配置信息,得到如下三个配置的配置值,并检查配置的合法:

1,读取request.timeout.ms配置项的值,默认值为40秒。用于配置请求的超时时间。

2,读取session.timeout.ms配置项的值,默认值为30秒,用于配置当前的consumer的session的超时时间,也就是client端多长时间不给server发送心跳就表示这个client端超时。

3,读取fetch.max.wait.ms配置项的值,默认值为500ms。用于配置从server中读取数据最长的等待时间。
        this.requestTimeoutMs = config.getInt(

                ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG);
        int sessionTimeOutMs = config.getInt(

                ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG);
        int fetchMaxWaitMs = config.getInt(

                ConsumerConfig.FETCH_MAX_WAIT_MS_CONFIG);

 

如果请求超时时间不是一个大于session的超时时间的值或者请求超时时间不是一个大于fetch的最大等待时间的值时,表示requestTimeoutMs的配置不合法,直接throw exception.
        if (this.requestTimeoutMs <= sessionTimeOutMs ||

                this.requestTimeoutMs <= fetchMaxWaitMs)
            throw new ConfigException(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG 

               " should be greater than " + ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG 

               " and " + ConsumerConfig.FETCH_MAX_WAIT_MS_CONFIG);

 

        this.time new SystemTime();

        MetricConfig metricConfig = new MetricConfig().samples(

                    config.getInt(ConsumerConfig.METRICS_NUM_SAMPLES_CONFIG))
                .timeWindow(config.getLong(

                        ConsumerConfig.METRICS_SAMPLE_WINDOW_MS_CONFIG),
                        TimeUnit.MILLISECONDS);

 

这里得到对应的consumer的client端id的client.id配置,如果这个值没有配置时,默认随机生成一个。
        clientId = config.getString(ConsumerConfig.CLIENT_ID_CONFIG);
        if (clientId.length() <= 0)
            clientId "consumer-" CONSUMER_CLIENT_ID_SEQUENCE.getAndIncrement();


        List<MetricsReporter> reporters = config.getConfiguredInstances(

                ConsumerConfig.METRIC_REPORTER_CLASSES_CONFIG,
                MetricsReporter.class);
        reporters.add(new JmxReporter(JMX_PREFIX));
        this.metrics new Metrics(metricConfigreporterstime);

 

读取retry.backoff.ms配置的值,默认值为100ms,用于配置重试的间隔周期。

        this.retryBackoffMs = config.getLong(

              ConsumerConfig.RETRY_BACKOFF_MS_CONFIG);

 

根据重试的间隔周期加上metadata.max.age.ms配置项的值生成Metadata实例,

配置metadata.max.age.ms项默认值为5分钟,用于设置metadata定期重新读取的生命周期。
        this.metadata new Metadata(retryBackoffMs

              config.getLong(ConsumerConfig.METADATA_MAX_AGE_CONFIG));

 

读取bootstrap.servers配置的要读取的kafka brokers的配置列表,并根据broker的连接信息,生成Cluster实例,并把Cluster实例更新到metadata的实例。
        List<InetSocketAddress> addresses = ClientUtils.parseAndValidateAddresses(

              config.getList(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG));
        this.metadata.update(Cluster.bootstrap(addresses)0);


        String metricGrpPrefix = "consumer";
        Map<StringString> metricsTags = new LinkedHashMap<StringString>();
        metricsTags.put("client-id"clientId);

 

生成NetworkClient的实例,生成实例需要如下几个配置文件:

1,配置项connections.max.idle.ms,默认值9分钟,用于配置连接最大的空闲时间(每个连接的最大连接队列为100)。

2,配置项reconnect.backoff.ms,默认值50ms,用于配置连接断开后重新连接的间隔时间。

3,配置项send.buffer.bytes,默认值128kb,用于配置SOCKET的SO_SNDBUF发送数据的缓冲区大小。

4,配置项receive.buffer.bytes,默认值32kb,用于配置SOCKET的SO_RCVBUF接收数据的缓冲区大小。

5,读取request.timeout.ms配置项的值,默认值为40秒。用于配置请求的超时时间。
        ChannelBuilder channelBuilder = ClientUtils.createChannelBuilder(

               config.values());
        NetworkClient netClient = new NetworkClient(

                new Selector(config.getLong(

                   ConsumerConfig.CONNECTIONS_MAX_IDLE_MS_CONFIG),

                   metricstimemetricGrpPrefixmetricsTagschannelBuilder),
                this.metadata,
                clientId,
                100// a fixed large enough value will suffice
                
config.getLong(ConsumerConfig.RECONNECT_BACKOFF_MS_CONFIG),
                config.getInt(ConsumerConfig.SEND_BUFFER_CONFIG),
                config.getInt(ConsumerConfig.RECEIVE_BUFFER_CONFIG),
                config.getInt(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG)time);

 

根据retry.backoff.ms配置的值,生成一个ConsumerNetworkClient的实例。
        this.client new ConsumerNetworkClient(netClientmetadatatime

                 retryBackoffMs);

 

读取auto.offset.reset配置项的值,默认值为latest。可配置("latest""earliest""none"),这个配置用于在读取partition的offset超出范围时,对offset进行重置的规则。
        OffsetResetStrategy offsetResetStrategy = OffsetResetStrategy.valueOf(

                    config.getString(

                    ConsumerConfig.AUTO_OFFSET_RESET_CONFIG).toUpperCase());

 

生成用于管理订阅的topic的partition的状态管理的组件,用于管理partition的状态与当前的offset的信息。
        this.subscriptions new SubscriptionState(offsetResetStrategy);

 

生成用于管理相同的一个groupId下的多个client端的partition的分区控制,

通过partition.assignment.strategy配置,默认实例为RangeAssignor
        List<PartitionAssignor> assignors = config.getConfiguredInstances(
                ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
                PartitionAssignor.class);

 

生成用于对consumer进行协调的实例,这个实例依赖如下配置:

1,配置项group.id,用于配置consumer对应的订阅的组名称,相同的组的多个client端进行协调消费处理。

2,读取session.timeout.ms配置项的值,默认值为30秒,用于配置当前的consumer的session的超时时间,也就是client端多长时间不给server发送心跳就表示这个client端超时。

3,配置项heartbeat.interval.ms,默认值3秒,用于定时向server发送心跳的时间间隔。

4,根据retry.backoff.ms配置的值来设置读取信息失败的重试间隔。

5,配置项enable.auto.commit,默认值true,设置是否自动提交消费过的offset的值的设置。

5,配置项auto.commit.interval.ms,默认值5秒,如果设置有自动提交offset时,自动提交的间隔时间。
        this.coordinator new ConsumerCoordinator(this.client,
                config.getString(ConsumerConfig.GROUP_ID_CONFIG),
                config.getInt(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG),
                config.getInt(ConsumerConfig.HEARTBEAT_INTERVAL_MS_CONFIG),
                assignors,
                this.metadata,
                this.subscriptions,
                metrics,
                metricGrpPrefix,
                metricsTags,
                this.time,
                retryBackoffMs,
                new ConsumerCoordinator.DefaultOffsetCommitCallback(),
                config.getBoolean(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG),
                config.getLong(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG));

 

根据key.deserializer配置与value.deserializer配置的key,value的反序列化的配置,生成反序列化消息的实例。这个类必须是实现Deserializer接口的类。
        if (keyDeserializer == null) {
            this.keyDeserializer = config.getConfiguredInstance(

                    ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
                    Deserializer.class);
            this.keyDeserializer.configure(config.originals()true);
        else {
            config.ignore(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG);
            this.keyDeserializer = keyDeserializer;
        }


        if (valueDeserializer == null) {
            this.valueDeserializer = config.getConfiguredInstance(

                    ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
                    Deserializer.class);
            this.valueDeserializer.configure(config.originals()false);
        else {
            config.ignore(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG);
            this.valueDeserializer = valueDeserializer;
        }

 

生成用于具体读取消息的读取实例,这个实例依赖如下几个配置信息:

1,配置项fetch.min.bytes,默认值1,用于设置每次读取的最小byte数。

2,配置项fetch.max.wait.ms,默认值500ms,用于设置每次读取的最大等待时间。

3,配置项max.partition.fetch.bytes,默认值1MB,用于设置每个partition每次读取的最大的数据量。

4,配置项check.crcs,默认值true,用于设置是否校验数据的完整性。

根据retry.backoff.ms配置的值来设置读取信息失败的重试间隔。
        this.fetcher new Fetcher<>(this.client,
                config.getInt(ConsumerConfig.FETCH_MIN_BYTES_CONFIG),
                config.getInt(ConsumerConfig.FETCH_MAX_WAIT_MS_CONFIG),
                config.getInt(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG),
                config.getBoolean(ConsumerConfig.CHECK_CRCS_CONFIG),
                this.keyDeserializer,
                this.valueDeserializer,
                this.metadata,
                this.subscriptions,
                metrics,
                metricGrpPrefix,
                metricsTags,
                this.time,
                this.retryBackoffMs);

        config.logUnused();
        AppInfoParser.registerAppInfo(JMX_PREFIXclientId);

        log.debug("Kafka consumer created");
    catch (Throwable t) {
        // call close methods if internal objects are already constructed
        // this is to prevent resource leak. see KAFKA-2121
        
close(true);
        

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值