SpringBoot通过SSL连接Docker Kafka失败,求排查解决
Kafka SSL连接问题:SpringBoot应用连接失败但Offset Explorer正常
Docker Compose配置(启用SSL的Kafka集群)
version: '2' services: zookeeper: image: confluentinc/cp-zookeeper:6.2.0 environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 ports: - 2181:2181 volumes: - ./data/zookeeper/data:/data - ./data/zookeeper/datalog:/datalog kafka: image: confluentinc/cp-kafka:6.2.0 depends_on: - zookeeper ports: - 9093:9093 - 9092:9092 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:19092,SSL://localhost:9093 KAFKA_SSL_CLIENT_AUTH: 'required' KAFKA_SSL_KEYSTORE_FILENAME: 'certs/server.keystore.jks' KAFKA_SSL_KEYSTORE_CREDENTIALS: 'certs/kafka_keystore_credentials' KAFKA_SSL_KEY_CREDENTIALS: 'certs/kafka_sslkey_credentials' KAFKA_SSL_TRUSTSTORE_FILENAME: 'certs/server.truststore.jks' KAFKA_SSL_TRUSTSTORE_CREDENTIALS: 'certs/kafka_truststore_credentials' KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true' KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 volumes: - ./certs:/etc/kafka/secrets/certs - ./data/kafka1/data:/var/lib/kafka/data
SpringBoot应用配置(application.yml)
server: port: 8888 spring: kafka: consumer: security: protocol: "SSL" bootstrap-servers: localhost:9093 group-id: group-tenant2-id auto-offset-reset: earliest key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer ssl: trust-store-location: classpath:client.truststore.jks trust-store-password: test123 producer: security: protocol: "SSL" bootstrap-servers: localhost:9093 key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer ssl: trust-store-location: classpath:client.truststore.jks trust-store-password: test123
报错信息
org.apache.kafka.common.errors.SslAuthenticationException: Failed to process post-handshake messages Caused by: javax.net.ssl.SSLException: Tag mismatch! at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:133) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:370) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308) ~[na:na] at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:123) ~[na:na] at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:736) ~[na:na] at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:691) ~[na:na] at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506) ~[na:na] at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482) ~[na:na] at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679) ~[na:na] at org.apache.kafka.common.network.SslTransportLayer.read(SslTransportLayer.java:569) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.NetworkReceive.readFrom(NetworkReceive.java:95) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.KafkaChannel.receive(KafkaChannel.java:452) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.KafkaChannel.read(KafkaChannel.java:402) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.Selector.attemptRead(Selector.java:674) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:576) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.common.network.Selector.poll(Selector.java:481) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:560) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:265) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:236) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:215) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureCoordinatorReady(AbstractCoordinator.java:246) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.coordinatorUnknownAndUnready(ConsumerCoordinator.java:459) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.poll(ConsumerCoordinator.java:487) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.KafkaConsumer.updateAssignmentMetadataIfNeeded(KafkaConsumer.java:1262) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1231) ~[kafka-clients-3.1.1.jar:na] at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1211) ~[kafka-clients-3.1.1.jar:na] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollConsumer(KafkaMessageListenerContainer.java:1529) ~[spring-kafka-2.8.8.jar:2.8.8] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doPoll(KafkaMessageListenerContainer.java:1519) ~[spring-kafka-2.8.8.jar:2.8.8] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1343) ~[spring-kafka-2.8.8.jar:2.8.8] at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:1255) ~[spring-kafka-2.8.8.jar:2.8.8] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
问题现象
Offset Explorer可正常通过SSL连接该Kafka集群:
解决方案
问题根源在于Kafka Broker配置了KAFKA_SSL_CLIENT_AUTH: 'required',要求客户端必须提供SSL证书完成双向认证,但当前SpringBoot配置仅配置了信任库(truststore),缺少客户端密钥库(keystore)的相关配置。
需要在SpringBoot的consumer和producer的ssl节点下添加以下配置:
key-store-location: classpath:client.keystore.jks key-store-password: 你的密钥库密码 key-password: 你的密钥密码
修改后的完整配置示例:
spring: kafka: consumer: security: protocol: "SSL" bootstrap-servers: localhost:9093 group-id: group-tenant2-id auto-offset-reset: earliest key-deserializer: org.apache.kafka.common.serialization.StringDeserializer value-deserializer: org.apache.kafka.common.serialization.StringDeserializer ssl: trust-store-location: classpath:client.truststore.jks trust-store-password: test123 key-store-location: classpath:client.keystore.jks key-store-password: test123 key-password: test123 producer: security: protocol: "SSL" bootstrap-servers: localhost:9093 key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer ssl: trust-store-location: classpath:client.truststore.jks trust-store-password: test123 key-store-location: classpath:client.keystore.jks key-store-password: test123 key-password: test123
同时确保client.keystore.jks已放置在SpringBoot项目的resources目录下,且配置中的密码与实际密钥库、密钥密码一致。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

