kafka.common.InconsistentBrokerIdException: Configured broker.id 3 doesn‘t match stored broker.id 4

博客内容描述了在启动Kafka服务时遇到的一个严重错误,即配置的Broker.id与存储的不符。解决方法包括将Broker.id设置为一致或删除元数据重新生成。这是一个关于Kafka服务器配置和故障排除的问题。

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

[2021-10-30 12:18:20,730] ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer)
kafka.common.InconsistentBrokerIdException: Configured broker.id 3 doesn’t match stored broker.id 4 in meta.properties. If you moved your data, make sure your configured broker.id matches. If you intend to create a new broker, you should remove all data in your data directories (log.dirs).
at kafka.server.KafkaServer.getOrGenerateBrokerId(KafkaServer.scala:759)
at kafka.server.KafkaServer.startup(KafkaServer.scala:223)
at kafka.server.KafkaServerStartable.startup(KafkaServerStartable.scala:44)
at kafka.Kafka$.main(Kafka.scala:84)
at kafka.Kafka.main(Kafka.scala)

vim server.pro

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Broker.id不一样,可以修改成一样,或者删除重新生成, 这里是删除掉
在这里插入图片描述

<think>我们有一个Spring Boot应用的配置文件片段,目标是连接MRS Kafka集群(使用Kerberos认证)。配置中使用了IP地址作为bootstrap servers,并提供了Kerberos相关的安全配置。 需要解决的问题:如何在Spring Boot应用中正确配置Kafka消费者,使其能够通过Kerberos认证连接到使用IP地址的MRS Kafka集群。 解决方案步骤: 1. 确保Kerberos配置文件(krb5.conf)和JAAS配置文件(jaas.conf)可用。 2. 在Spring Boot应用中,通过配置属性设置Kafka消费者的相关参数,特别是Kerberos认证所需的参数。 3. 解决使用IP地址连接时Kerberos认证的主机名验证问题(因为Kerberos票据通常基于主机名,而非IP)。 4. 在应用启动时加载JAAS配置,并设置Kerberos相关系统属性。 具体实现: 步骤1:准备Kerberos配置文件 - 将krb5.conf文件放在资源目录下或指定路径(例如/etc/krb5.conf)。 - 创建JAAS配置文件(例如kafka_client_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"; }; 步骤2:在Spring Boot配置文件中添加Kafka消费者配置(application.yml) - 注意:配置中已经包含了一些Kafka消费者配置,但需要补充Kerberos认证相关的配置。 步骤3:解决IP地址问题 - 在连接IP地址时,Kerberos会验证服务主体(Service Principal Name, SPN)中的主机名。由于我们使用IP,因此需要覆盖默认的主机名验证。 - 通过设置`sasl.kerberos.host.name`属性为一个虚拟的主机名(该主机名需要与Kafka Broker配置的Kerberos主体中的主机名一致),来绕过主机名验证。 步骤4:编写Java配置类,设置系统属性并初始化JAAS配置 代码实现: 1. 创建JAAS配置文件(假设放在项目根目录下的conf目录中,或使用绝对路径) 2. 修改application.yml,添加以下配置(注意:原配置已有一部分,需要补充): ```yaml mrs: kafka: # ... 其他配置 properties: sasl.jaas.config: org.apache.kafka.common.security.kerberos.KerberosLoginModule required useKeyTab=true storeKey=true keyTab="${mrs.kafka.security.user-keytab-file}" principal="${mrs.kafka.security.user-principal}"; security.protocol: ${mrs.kafka.security-protocol} sasl.mechanism: GSSAPI sasl.kerberos.service.name: ${mrs.kafka.sasl-kerberos-service-name} # 解决IP地址问题:设置一个虚拟主机名(需要与Broker的Kerberos主体中的主机名匹配) sasl.kerberos.host.name: kafka.hadoop.com # 这里需要根据实际情况修改,可以是Broker配置的主机名 ``` 但是注意:Spring Kafka的配置中,我们可以通过`spring.kafka.properties.*`来设置任意Kafka客户端属性。但是这里我们使用的是自定义前缀`mrs.kafka`,所以我们需要在配置类中将这些属性映射到Spring Kafka的配置中。 3. 由于我们使用了自定义配置前缀,我们需要创建一个配置类来将`mrs.kafka`下的配置映射到Spring Kafka的`ConcurrentKafkaListenerContainerFactory`和`ConsumerFactory`。 4. 在应用启动时设置系统属性(可选,如果JAAS配置通过系统属性设置): - 在main方法中设置: ```java public static void main(String[] args) { // 设置krb5.conf的位置,如果不在默认位置 System.setProperty("java.security.krb5.conf", "/path/to/krb5.conf"); // 设置JAAS配置,但注意:Kafka客户端也可以直接通过属性`sasl.jaas.config`配置,这样就不需要系统属性 // System.setProperty("java.security.auth.login.config", "/path/to/kafka_client_jaas.conf"); SpringApplication.run(Application.class, args); } ``` 5. 配置Kafka消费者工厂: 由于我们使用自定义配置,所以需要创建一个配置类,将`mrs.kafka`下的配置映射到Kafka消费者属性。 配置类示例: ```java import org.apache.kafka.clients.consumer.ConsumerConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.core.DefaultKafkaConsumerFactory; import java.util.HashMap; import java.util.Map; @Configuration public class KafkaConfig { @Value("${mrs.kafka.bootstrap-servers}") private String bootstrapServers; @Value("${mrs.kafka.consumer.group-id}") private String groupId; @Value("${mrs.kafka.consumer.auto-offset-reset}") private String autoOffsetReset; @Value("${mrs.kafka.consumer.enable-auto-commit}") private boolean enableAutoCommit; @Value("${mrs.kafka.consumer.auto-commit-interval-ms}") private int autoCommitIntervalMs; @Value("${mrs.kafka.consumer.key-deserializer}") private String keyDeserializer; @Value("${mrs.kafka.consumer.value-deserializer}") private String valueDeserializer; // 安全配置 @Value("${mrs.kafka.security-protocol}") private String securityProtocol; @Value("${mrs.kafka.sasl-kerberos-service-name}") private String saslKerberosServiceName; @Value("${mrs.kafka.security.user-keytab-file}") private String keyTabLocation; @Value("${mrs.kafka.security.user-principal}") private String principal; // 如果配置了sasl.kerberos.host.name @Value("${mrs.kafka.properties.sasl.kerberos.host.name:#{null}}") private String saslKerberosHostName; @Bean public Map<String, Object> consumerConfigs() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, enableAutoCommit); props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, autoCommitIntervalMs); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyDeserializer); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, valueDeserializer); // Kerberos 安全配置 props.put("security.protocol", securityProtocol); props.put("sasl.mechanism", "GSSAPI"); props.put("sasl.kerberos.service.name", saslKerberosServiceName); // 通过JAAS配置属性设置,这样就不需要外部的JAAS文件 String jaasConfig = String.format( "com.sun.security.auth.module.Krb5LoginModule required " + "useKeyTab=true " + "storeKey=true " + "keyTab=\"%s\" " + "principal=\"%s\";", keyTabLocation, principal); props.put("sasl.jaas.config", jaasConfig); // 如果配置了sasl.kerberos.host.name,则设置 if (saslKerberosHostName != null) { props.put("sasl.kerberos.host.name", saslKerberosHostName); } return props; } @Bean public ConsumerFactory<String, String> consumerFactory() { return new DefaultKafkaConsumerFactory<>(consumerConfigs()); } @Bean public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); // 其他设置,如并发数等 return factory; } } ``` 6. 在监听器类中使用`@KafkaListener`注解消费消息: ```java import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component public class KafkaMessageListener { @KafkaListener(topics = "${mrs.kafka.consumer.topics}", groupId = "${mrs.kafka.consumer.group-id}") public void listen(String message) { System.out.println("Received Message: " + message); } } ``` 7. 注意:在配置文件中,我们使用`mrs.kafka.consumer.topics`来指定要监听的多个主题,因此需要确保在配置文件中正确列出。 8. 关于`keyTabLocation`的路径:如果keytab文件放在资源目录下,可以使用`file:./user.keytab`或者使用绝对路径。建议将keytab文件放在安全的位置,并通过绝对路径引用。 9. 解决IP地址连接的关键点: - 设置`sasl.kerberos.host.name`属性,值为Broker的Kerberos主体中的主机名(例如,Broker的Kerberos主体为`kafka/kafka.hadoop.com@HADOOP.COM`,则这里设置为`kafka.hadoop.com`)。 - 如果Broker有多个,每个Broker的Kerberos主体中的主机名应该相同(或者使用通配符主体),或者为每个Broker设置相同的主机名映射。 10. 如果Broker的Kerberos主体使用的主机名是IP地址(不常见),则不需要设置`sasl.kerberos.host.name`,但通常不推荐这样做。 11. 测试:启动应用,查看是否能够正常消费消息。 注意事项: - Kerberos票据的续期:Kafka客户端会自动刷新票据,但需要确保keytab文件有效。 - 如果遇到认证失败,可以启用Kerberos调试:在JVM参数中添加`-Dsun.security.krb5.debug=true`。 通过以上步骤,Spring Boot应用应该能够通过Kerberos认证连接使用IP地址的MRS Kafka集群。 相关问题: 由于问题已经解决,下面提出相关问题: §§相关问题§§: 1. 在Spring Kafka中如何同时消费多个主题? 2.Kafka集群使用动态DNS时,如何配置Spring Kafka客户端以适应主机名的变化? 3. 如何为Spring Kafka消费者配置错误处理(如反序列化错误)? 4. 在Kerberos认证的Kafka集群中,如何实现Keytab文件的动态更新而不重启应用?</think>### Spring Boot 集成 MRS Kerberos 认证 Kafka 解决方案 以下是完整的 Spring Boot 应用配置和代码实现,用于连接使用 IP 地址的 MRS Kerberos 认证 Kafka 集群: #### 1. 完整的 `application.yml` 配置优化 ```yaml server: port: 8080 spring: application: name: kafka-mea-listener kafka: bootstrap-servers: 25.45.48.105:21007,25.45.48.191:21007,25.45.49.19:21007 properties: security.protocol: SASL_PLAINTEXT sasl.mechanism: GSSAPI sasl.kerberos.service.name: kafka # 解决IP地址连接问题 sasl.kerberos.host.name: kafka-broker.hadoop.hadoop.com # JAAS配置 sasl.jaas.config: | com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab="${mrs.kafka.security.user-keytab-file}" principal="${mrs.kafka.security.user-principal}"; consumer: group-id: test001 auto-offset-reset: earliest enable-auto-commit: true auto-commit-interval: 10000 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer # 增加以下关键配置 properties: session.timeout.ms: 10000 max.poll.interval.ms: 300000 request.timeout.ms: 40000 mrs: kafka: security: user-keytab-file: classpath:user.keytab # 或绝对路径 /path/to/user.keytab user-principal: sh_sjzt_dwzy@HADOOP.COM topics: - topic1 - topic2 ``` #### 2. Kerberos 初始化配置类 ```java import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; @Configuration public class KerberosConfig { @Value("${mrs.kafka.security.user-keytab-file}") private String keytabPath; @Value("${mrs.kafka.security.user-principal}") private String principal; @PostConstruct public void initKerberos() { // 设置Kerberos环境 System.setProperty("java.security.krb5.conf", "/etc/krb5.conf"); System.setProperty("sun.security.krb5.debug", "true"); // 调试模式 // 自动获取Kerberos票据 try { String kinitCmd = String.format("kinit -k -t %s %s", resolveKeytabPath(keytabPath), principal); Runtime.getRuntime().exec(kinitCmd); } catch (Exception e) { throw new RuntimeException("Kerberos初始化失败", e); } } private String resolveKeytabPath(String path) { if (path.startsWith("classpath:")) { String resource = path.substring(10); return new ClassPathResource(resource).getFile().getAbsolutePath(); } return path; } } ``` #### 3. Kafka 消费者监听器 ```java import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component public class KafkaKerberosConsumer { @KafkaListener(topics = "#{&#39;${mrs.kafka.topics}&#39;.split(&#39;,&#39;)}", groupId = "${spring.kafka.consumer.group-id}") public void listen(String message) { System.out.println("收到消息: " + message); // 业务处理逻辑 } // 处理消费异常 @KafkaListener(id = "errorHandler", topics = "${spring.kafka.consumer.error-topic}") public void handleError(ConsumerRecord<?, ?> record, Exception ex) { System.err.printf("消息处理失败: 主题=%s, 分区=%d, 偏移量=%d, 原因=%s%n", record.topic(), record.partition(), record.offset(), ex.getMessage()); } } ``` #### 4. 自动票据续期组件 ```java import org.apache.kafka.common.security.kerberos.KerberosLogin; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import sun.security.krb5.internal.Krb5; @Component public class KerberosTicketRenewer { private KerberosLogin kerberosLogin; @Scheduled(fixedRate = 3600000) // 每小时执行一次 public void renewTicket() { if (kerberosLogin == null) { kerberosLogin = new KerberosLogin(); kerberosLogin.configure(Collections.emptyMap(), null); } try { if (kerberosLogin.getSubject() != null) { kerberosLogin.relogin(); System.out.println("Kerberos票据已成功续期"); } } catch (Exception e) { System.err.println("票据续期失败: " + e.getMessage()); } } } ``` #### 5. 健康检查端点 ```java import org.apache.kafka.clients.consumer.KafkaConsumer; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; @Component public class KafkaHealthCheck implements HealthIndicator { private final KafkaConsumer<String, String> consumer; public KafkaHealthCheck(KafkaConsumer<String, String> consumer) { this.consumer = consumer; } @Override public Health health() { try { consumer.listTopics(); // 测试连接 return Health.up().withDetail("brokers", consumer.bootstrapServers()).build(); } catch (Exception e) { return Health.down(e).build(); } } } ``` #### 6. 关键问题解决方案 1. **IP地址连接问题**: ```yaml sasl.kerberos.host.name: kafka-broker.hadoop.hadoop.com ``` - 在Broker服务器上执行获取实际主机名: ```bash klist -k /etc/security/keytabs/kafka.service.keytab # 输出示例:kafka/kafka-broker.hadoop.hadoop.com@HADOOP.COM ``` 2. **Keytab路径处理**: - 开发环境:`classpath:user.keytab` - 生产环境:`/etc/security/keytabs/user.keytab` - 使用`ClassPathResource`自动解析路径 3. **Kerberos调试**: ```java System.setProperty("sun.security.krb5.debug", "true"); ``` 日志中会显示详细的Kerberos认证过程 #### 7. Docker部署配置 ```dockerfile FROM openjdk:11-jdk-slim # 安装Kerberos客户端 RUN apt-get update && apt-get install -y krb5-user # 复制应用和配置文件 COPY target/kafka-listener.jar /app.jar COPY conf/krb5.conf /etc/krb5.conf COPY conf/user.keytab /etc/security/keytabs/user.keytab # 设置环境变量 ENV JAVA_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf" ENTRYPOINT ["java","-jar","/app.jar"] ``` #### 8. 常见问题排查 1. **认证失败**: ```bash kinit -kt /etc/security/keytabs/user.keytab sh_sjzt_dwzy@HADOOP.COM klist # 验证票据 ``` 2. **主机名解析**: 在`/etc/hosts`中添加: ``` 25.45.48.105 kafka-broker.hadoop.hadoop.com 25.45.48.191 kafka-broker.hadoop.hadoop.com 25.45.49.19 kafka-broker.hadoop.hadoop.com ``` 3. **防火墙检查**: ```bash telnet 25.45.48.105 21007 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值