关于kafka Consumer参数:exclude.internal.topics

本文详细解析了Kafka中一个容易被误解的参数——excludeInternalTopics。该参数控制是否允许消费者通过正则表达式订阅的方式接收到内部Topic的消息。文章通过源码分析,澄清了官方文档表述可能引发的混淆。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前对这个参数一直理解有误,彻底搞清楚后就写个笔记记录一下。(基于kafka1.0)

先看官方文档的解释:Whether records from internal topics (such as offsets) should be exposed to the consumer. If set to true the only way to receive records from an internal topic is subscribing to it.

大意是:这个参数用于是否把内部topic的信息(例如offset)暴露给cosumer,如果设置为true,就只能通过订阅的方式来获取内部topic的数据。

也正是官网的这个解释让我有了错误理解,从参数的字面意思来看是“排除内部topic”,所以一直以为是设置为true就是排除内部topic,设置为false就是暴露内部topic,但实际测试却有不是这样的,于是看了相关的源码:

1.  //ConsumerCoordinator.java
2.  public void updatePatternSubscription(Cluster cluster) {
3.      final Set<String> topicsToSubscribe = new HashSet<>();
4.      //主要是下面这一句
5.      for (String topic : cluster.topics())
6.          if (subscriptions.subscribedPattern().matcher(topic).matches() &&
7.                  !(excludeInternalTopics && cluster.internalTopics().contains(topic)))
8.              topicsToSubscribe.add(topic);
9.  
10.     subscriptions.subscribeFromPattern(topicsToSubscribe);
11. 
    // note we still need to update the topics contained in the metadata. Although we have
    // specified that all topics should be fetched, only those set explicitly will be retained
        metadata.setTopics(subscriptions.groupSubscription());
}

从第6行看,原来还可以用正则的方式来订阅topic (孤陋寡闻了,从来就这么用过),加上第7行的两个条件,就明白了这个参数的意图。

__consumer_offsets是kafka server中一个默认的topic名,当用户有一个topic叫sumer_off,且用正则的方式来订阅topic,如下所示:

Pattern pattern = Pattern.compile(".*umer_of.*");
consumer.subscribe(pattern);

那么正则会匹配到__consumer_offsets这个内部topic,所以就用这个参数来限制是否暴露内部topic,当设置为true是,就算正则匹配中了内部topic,也不会消息,此时只能通过订阅的方式来消费内部topic,当这个参数设置为false时,如果正则匹配到内部topic,就会消费到内部topic的数据。

个人认识官方文档应该提及这个参数与正则订阅方式的联系,否则单从文档上很难看懂这个参数的意思。

<think>根据提供的配置信息,这是一个Kafka消费者的配置,特别是使用了SASL_PLAINTEXT安全协议和Kerberos认证。配置中包含了连接Kafka集群所需的各种参数,如bootstrap servers、安全协议、会话超时、重试次数等,以及消费者特定的配置,如group.id、自动提交偏移量等。 然而,这个配置看起来像是用YAML格式写的,可能是用于Spring Kafka或者类似的框架。但是,请注意,配置中的一些键可能不符合Spring Kafka的常规命名(例如,`Key-deserializer`中的大写字母K,而通常Spring Kafka使用小写和驼峰命名)。此外,配置中同时出现了消费者和生产者的一些配置(如key-serializer和value-serializer是生产者使用的,而deserializer是消费者使用的),这可能是配置中的一个错误,因为一个配置通常只针对消费者或生产者。 由于问题中没有明确说明具体需要什么帮助,我假设你需要一个使用这些配置的Kafka消费者的代码示例。这里我将使用Spring Kafka来演示,因为配置看起来像是Spring风格的。 注意:由于配置中包含了Kerberos认证,我们需要在代码中设置JAAS配置。在Spring Kafka中,我们可以通过设置系统属性来实现。 以下是一个Spring Boot应用程序的示例,它使用上述配置来创建一个Kafka消费者。 步骤: 1. 创建一个Spring Boot项目,添加spring-kafka依赖。 2. 将提供的配置转换为Spring Boot的application.yml格式。 3. 编写一个消费者监听器。 但是,请注意,配置中的一些属性需要调整以符合Spring Kafka的配置属性命名规则。例如: - `bootstrap-servers` -> `bootstrap-servers` (保持不变,但注意在Spring中是小写和连字符) - `security-protocol` -> `properties.security.protocol` (在Spring中,我们需要通过`properties`设置) - `sasl-kerberos-service-name` -> `properties.sasl.kerberos.service.name` - 等等。 另外,对于Kerberos认证,我们需要设置JAAS配置。可以通过在启动JVM时设置系统属性,或者在代码中设置。 由于配置中指定了`user-keytab-file`和`user-principal`,我们可以使用这些来构建JAAS配置。 我们可以在应用启动时动态设置JAAS配置,例如在main方法中。 下面是一个示例代码: 首先,调整配置文件(application.yml): ```yaml spring: kafka: bootstrap-servers: 25.45.48.105:21007,25.45.48.191:21007,25.45.49.19:21007 properties: security.protocol: SASL_PLAINTEXT sasl.kerberos.service.name: kafka # 注意:其他需要设置的属性如session.timeout.ms等,也可以在properties下设置 consumer: group-id: test001 auto-offset-reset: earliest enable-auto-commit: true auto-commit-interval: 10000 # 注意配置中写的是auto-commit-interval-ms,这里Spring Kafka使用auto-commit-interval,单位是毫秒,但这里配置值应该是一个整数,表示毫秒。 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer # 以下两个序列化器是生产者使用的,消费者不需要,所以去掉 # 注意:配置中还有retries, linger-ms等,这些是生产者配置,如果只做消费者,可以忽略 # 但是,如果同时需要生产者和消费者,需要分别配置 # 这里我们只配置消费者 # 自定义的kerberos配置 kerberos: user-keytab-file: user.keytab user-principal: sh_sjzt_dwzy@HADOOP.COM ``` 然后,在Spring Boot主类中设置JAAS配置: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class KafkaConsumerApplication { public static void main(String[] args) { // 从配置文件中读取kerberos配置,这里为了简单,直接使用系统属性设置,实际可以从环境变量或配置文件读取 // 注意:在实际应用中,这些配置应该通过外部配置(如application.yml)获取,这里为了演示,假设已经通过配置文件设置 // 我们将在启动时设置系统属性,以便JAAS使用 // 设置JAAS配置,这里我们使用keytab和principal // 注意:这里我们假设keytab文件在类路径下,或者指定了绝对路径 System.setProperty("java.security.auth.login.config", "path/to/jaas.conf"); // 但是,我们也可以动态构建JAAS配置字符串,然后通过系统属性设置 // 或者,我们可以使用-Djava.security.auth.login.config=jaas.conf在启动时传入 // 由于我们无法在代码中直接设置JAAS配置,除非我们使用一个配置文件,所以这里建议使用外部配置文件。 // 因此,我们在这里不设置,而是要求用户提供一个jaas.conf文件,并在启动时指定。 SpringApplication.run(KafkaConsumerApplication.class, args); } } ``` 但是,更常见的做法是在启动命令中指定JAAS配置文件,例如: ``` java -Djava.security.auth.login.config=/path/to/jaas.conf -jar your-app.jar ``` jaas.conf文件内容示例: ``` KafkaClient { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab="/path/to/user.keytab" principal="sh_sjzt_dwzy@HADOOP.COM"; }; ``` 注意:上面的keyTab路径需要是绝对路径,或者确保文件存在的位置。 然后,我们编写一个消费者监听器: ```java import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component public class KafkaConsumer { @KafkaListener(topics = {"xx", "yy"}) // 这里配置要监听的topic public void consume(String message) { System.out.println("Received message: " + message); // 处理消息 } } ``` 但是,配置中topics是在配置文件中指定的,我们希望动态读取。我们可以使用`@KafkaListener`的topics属性支持SpEL表达式,从配置文件中注入。 首先,在配置文件中添加topics的配置(在application.yml中): ```yaml myapp: kafka: topics: - xx - yy ``` 然后,在消费者中: ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; import java.util.List; @Component public class KafkaConsumer { @Value("${myapp.kafka.topics}") private List<String> topics; @KafkaListener(topics = "#{'${myapp.kafka.topics}'.split(',')}") // 注意:如果配置是列表,可以直接使用 // 但是,在application.yml中,myapp.kafka.topics是一个列表,所以可以直接注入为List // 但是@KafkaListener的topics参数是String[],所以我们可以直接转换 // 实际上,@KafkaListener支持直接使用List,所以我们可以这样写: @KafkaListener(topics = "#{@myTopics}") // 但是更简单的方式是直接使用topics变量,但需要确保topics变量是数组或可变参数 // 由于我们注入的是List,可以转换为数组 public void consume(String message) { System.out.println("Received message: " + message); } } ``` 但是,更简单的方式是直接使用配置属性: ```java @Component public class KafkaConsumer { @KafkaListener(topics = "#{'${myapp.kafka.topics}'.split(',')}") public void consume(String message) { // ... } } ``` 但是,在YAML中,如果myapp.kafka.topics是一个列表,那么使用SpEL表达式`'${myapp.kafka.topics}'`会得到一个字符串,例如"[xx, yy]",这样split会得到一个包含一个元素的数组(即整个字符串),所以这样不行。 我们可以使用另一种方式:在配置类中暴露一个数组: ```java @Configuration public class KafkaConfig { @Value("${myapp.kafka.topics}") private List<String> topics; @Bean public List<String> kafkaTopics() { return topics; } } ``` 然后在@KafkaListener中使用: ```java @KafkaListener(topics = "#{@kafkaTopics}") ``` 但是,@KafkaListener的topics属性需要String[],所以我们可以: ```java @Bean public String[] kafkaTopicsArray() { return topics.toArray(new String[0]); } ``` 然后: ```java @KafkaListener(topics = "#{@kafkaTopicsArray}") ``` 或者,我们可以直接在@KafkaListener中指定多个topic,但这样不够灵活。 考虑到配置的复杂性,这里我们简化处理,假设我们直接在注解中写死topics,或者使用配置文件注入到属性中,然后在@KafkaListener中使用。 由于问题中配置的topics是列表,我们可以这样写: ```yaml myapp: kafka: topics: xx,yy # 注意这里用逗号分隔的字符串 ``` 然后: ```java @KafkaListener(topics = "#{'${myapp.kafka.topics}'.split(',')}") ``` 这样就可以了。 但是,原始配置中topics是一个列表,所以如果我们使用YAML列表,那么我们可以这样注入: ```java @Value("${myapp.kafka.topics}") private String[] topics; // 注意:这里使用数组 @KafkaListener(topics = "${myapp.kafka.topics}") // 这样不行,因为topics属性是数组,不能直接使用字符串 ``` 所以,我们使用SpEL表达式: ```java @KafkaListener(topics = "#{@valueConfig.getTopics}") ``` 其中,valueConfig是一个Bean,它提供了getTopics方法返回数组。 为了简化,我们使用逗号分隔的字符串配置。 修改application.yml: ```yaml myapp: kafka: topics: xx,yy ``` 然后: ```java @Component public class KafkaConsumer { @KafkaListener(topics = "#{'${myapp.kafka.topics}'.split(',')}") public void consume(String message) { // ... } } ``` 这样就可以了。 总结:我们创建了一个Spring Boot应用,配置了Kafka消费者,使用Kerberos认证,通过keytab文件进行认证。我们通过外部JAAS配置文件指定了Kerberos认证信息,并在Spring Kafka的配置中设置了相应的属性。 注意:由于Kerberos配置的复杂性,确保你的Kafka集群配置正确,并且keytab文件有效,且principal正确。 另外,关于配置中的其他属性,如`session-timeout-ms`,在Spring Kafka中,我们可以通过`spring.kafka.consumer.properties.session.timeout.ms`来设置,例如: ```yaml spring: kafka: consumer: properties: session.timeout.ms: 10000 ``` 同样,`retries`和`linger-ms`是生产者配置,这里我们不需要。 最后,由于配置中包含了`ack: 1`,这是生产者的配置,所以我们在消费者配置中忽略它。 由于问题中没有具体说明需求,以上代码和配置创建了一个基本的消费者。如果有其他需求,请进一步说明。 §§相关问题§§: 1. 如何在Spring Kafka中配置多个Kafka消费者? 2. 如何处理Kafka消息消费时的异常? 3. 如何手动提交Kafka消费偏移量? 4. 如何在Spring Kafka中配置Kerberos认证而不使用外部JAAS配置文件?</think>### Kafka消费者配置与实现 根据您提供的YAML配置,这是一个使用Kerberos认证的Kafka消费者配置。我将展示如何使用Spring Boot实现这个消费者,并解释关键配置项。 #### 关键配置项解析: 1. **bootstrap-servers**:Kafka集群地址 2. **security-protocol**:使用SASL_PLAINTEXT安全协议 3. **kerberos认证**:需要keytab文件和principal 4. **消费者配置**: - group-id:消费者组ID - auto-offset-reset:从最早偏移量开始消费 - 序列化/反序列化配置 #### Spring Boot实现代码 ```java // 1. 添加Maven依赖 /* <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> */ // 2. 配置文件 (application.yml) spring: kafka: bootstrap-servers: 25.45.48.105:21007,25.45.48.191:21007,25.45.49.19:21007 properties: security.protocol: SASL_PLAINTEXT sasl.kerberos.service.name: kafka session.timeout.ms: 10000 consumer: group-id: test001 auto-offset-reset: earliest enable-auto-commit: true auto-commit-interval-ms: 10000 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer # Kerberos认证配置 jaas: enabled: true loginModule: com.sun.security.auth.module.Krb5LoginModule controlFlag: REQUIRED options: useKeyTab: true storeKey: true keyTab: "/path/to/user.keytab" # 实际keytab文件路径 principal: sh_sjzt_dwzy@HADOOP.COM ``` ```java // 3. 消费者实现类 import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component public class KafkaMessageListener { // 监听配置文件中指定的多个topic @KafkaListener(topics = "#{'${spring.kafka.consumer.topics}'.split(',')}") public void listen(String message) { System.out.println("Received Message: " + message); // 这里添加业务处理逻辑 } } ``` ```java // 4. 主应用类 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class KafkaConsumerApplication { public static void main(String[] args) { // 设置Kerberos环境变量 System.setProperty("java.security.krb5.conf", "/path/to/krb5.conf"); SpringApplication.run(KafkaConsumerApplication.class, args); } } ``` #### 代码说明: 1. **Kerberos配置**: - 使用`jaas.options`配置keytab和principal - 需要设置`krb5.conf`文件路径(通过系统属性) - 实际部署时需要替换keytab和krb5.conf的实际路径 2. **消费者特性**: - 自动提交偏移量(每10秒提交一次) - 从最早偏移量开始消费(auto-offset-reset: earliest) - 使用字符串反序列化器 3. **多主题监听**: - `@KafkaListener`支持监听多个topic - 主题列表从配置文件动态获取 #### 部署注意事项: 1. 将`user.keytab`和`krb5.conf`文件放在安全位置 2. 在KDC中确保principal有效 3. 防火墙开放21007端口 4. 测试连接性:`telnet 25.45.48.105 21007`
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值