Spring Boot3迁移后Kafka AvroSerializer无法读取SSL配置致PKIX错误
Spring Boot 3迁移后Avro Serializer无法读取Schema Registry SSL配置问题解决
问题背景
我近期将应用从Spring Boot 2.6.x迁移至Spring Boot 3.0.2,该应用需与Kafka及采用自签名证书的Schema Registry交互,证书已导入信任库与密钥库。经排查,问题与AvroSerializer(版本从5升级至7)相关,它无法读取配置文件中的SSL配置。从日志可见KafkaAvroSerializerConfig里Schema Registry的SSL相关路径均为null,应用启动时出现SSL握手失败,抛出javax.net.ssl.SSLHandshakeException: PKIX path building failed错误。
当前技术栈:
- Spring Boot 3.0.2
- Kafka Avro Serializer 7.3.1
- Spring Kafka 3.0.2
- Spring 6.0.4
解决方案
1. 明确Schema Registry SSL配置前缀
Confluent 7.x版本的AvroSerializer不再自动继承Spring Kafka的配置,需使用schema.registry.ssl.*前缀单独配置Schema Registry的SSL参数,在application.properties中添加:
# Schema Registry基础地址 schema.registry.url=https://your-schema-registry-url:port # Schema Registry SSL配置 schema.registry.ssl.truststore.location=/path/to/your/truststore.jks schema.registry.ssl.truststore.password=your-truststore-password schema.registry.ssl.keystore.location=/path/to/your/keystore.jks schema.registry.ssl.keystore.password=your-keystore-password schema.registry.ssl.key.password=your-key-password
2. 显式传递配置到Kafka生产者/消费者工厂
在Spring Kafka配置类中,需将Schema Registry的SSL配置手动注入到生产者/消费者的配置属性中,确保AvroSerializer能获取到这些参数:
@Configuration public class KafkaConfig { @Value("${schema.registry.url}") private String schemaRegistryUrl; @Value("${schema.registry.ssl.truststore.location}") private String truststoreLocation; @Value("${schema.registry.ssl.truststore.password}") private String truststorePassword; @Value("${schema.registry.ssl.keystore.location}") private String keystoreLocation; @Value("${schema.registry.ssl.keystore.password}") private String keystorePassword; @Value("${schema.registry.ssl.key.password}") private String keyPassword; @Bean public ProducerFactory<String, Object> producerFactory() { Map<String, Object> configProps = new HashMap<>(); // 基础Kafka生产者配置 configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "your-kafka-bootstrap-servers"); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class); // 注入Schema Registry配置 configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl); configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_TRUSTSTORE_LOCATION_CONFIG, truststoreLocation); configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_TRUSTSTORE_PASSWORD_CONFIG, truststorePassword); configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEYSTORE_LOCATION_CONFIG, keystoreLocation); configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEYSTORE_PASSWORD_CONFIG, keystorePassword); configProps.put(KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEY_PASSWORD_CONFIG, keyPassword); return new DefaultKafkaProducerFactory<>(configProps); } // 消费者工厂需做类似配置,将值注入到KafkaAvroDeserializer的配置中 @Bean public ConsumerFactory<String, Object> consumerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "your-kafka-bootstrap-servers"); configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KafkaAvroDeserializer.class); // 注入Schema Registry配置 configProps.put(KafkaAvroDeserializerConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl); configProps.put(KafkaAvroDeserializerConfig.SCHEMA_REGISTRY_SSL_TRUSTSTORE_LOCATION_CONFIG, truststoreLocation); // 其他SSL配置项同上... return new DefaultKafkaConsumerFactory<>(configProps); } }
3. 核对Confluent 7.x配置常量
确保使用的配置常量与Confluent 7.x版本匹配,避免因属性名变更导致读取失败:
- 信任库路径:
KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_TRUSTSTORE_LOCATION_CONFIG - 信任库密码:
KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_TRUSTSTORE_PASSWORD_CONFIG - 密钥库路径:
KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEYSTORE_LOCATION_CONFIG - 密钥库密码:
KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEYSTORE_PASSWORD_CONFIG - 密钥密码:
KafkaAvroSerializerConfig.SCHEMA_REGISTRY_SSL_KEY_PASSWORD_CONFIG
4. 验证证书导入有效性
确认信任库中已正确导入Schema Registry的自签名证书,可通过以下命令检查:
keytool -list -v -keystore /path/to/your/truststore.jks
查看输出是否包含目标证书的条目。
内容的提问来源于stack exchange,提问作者ufasoli
相关产品推荐
相关产品推荐

