PySpark写入Cassandra遇SSL版本不匹配错误如何解决?
问题
尝试通过DataStax Spark Cassandra Connector将PySpark DataFrame保存至Cassandra数据库,已设置spark.cassandra.connection.ssl.enabled参数,执行保存操作时,Cassandra日志和Python进程分别出现如下错误:
Cassandra日志错误
WARN [epollEventLoopGroup-5-32] 2023-05-05 16:35:04,962 PreV5Handlers.java:261 - Unknown exception in client networking io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:478) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:829)
Python进程错误
INFO - : java.io.IOException: Failed to open native connection to Cassandra at {10.230.88.101}:9042 INFO - at com.datastax.spark.connector.cql.CassandraConnector$.com$datastax$spark$connector$cql$CassandraConnector$$createSession(CassandraConnector.scala:168) INFO - at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$8.apply(CassandraConnector.scala:154) INFO - at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$8.apply(CassandraConnector.scala:154) INFO - at com.datastax.spark.connector.cql.RefCountedCache.createNewValueAndKeys(RefCountedCache.scala:32) INFO - at com.datastax.spark.connector.cql.RefCountedCache.syncAcquire(RefCountedCache.scala:69) INFO - at com.datastax.spark.connector.cql.RefCountedCache.acquire(RefCountedCache.scala:57) INFO - at com.datastax.spark.connector.cql.CassandraConnector.openSession(CassandraConnector.scala:79) INFO - at com.datastax.spark.connector.cql.CassandraConnector.withSessionDo(CassandraConnector.scala:111) INFO - at com.datastax.spark.connector.rdd.partitioner.dht.TokenFactory$.forSystemLocalPartitioner(TokenFactory.scala:98) INFO - at org.apache.spark.sql.cassandra.CassandraSourceRelation$.apply(CassandraSourceRelation.scala:276) INFO - at org.apache.spark.sql.cassandra.DefaultSource.createRelation(DefaultSource.scala:83) INFO - at org.apache.spark.sql.execution.datasources.SaveIntoDataSourceCommand.run(SaveIntoDataSourceCommand.scala:45) INFO - at org.apache.spark.sql.execution.command.ExecutedCommandExec.sideEffectResult$lzycompute(commands.scala:70) INFO - at org.apache.spark.sql.execution.command.ExecutedCommandExec.sideEffectResult(commands.scala:68) INFO - at org.apache.spark.sql.execution.command.ExecutedCommandExec.doExecute(commands.scala:86) INFO - at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:131) INFO - at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:127) INFO - at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:155) INFO - at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151) INFO - at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:152) INFO - at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:127) INFO - at org.apache.spark.sql.execution.QueryExecution.toRdd$lzycompute(QueryExecution.scala:80) INFO - at org.apache.spark.sql.execution.QueryExecution.toRdd(QueryExecution.scala:80) INFO - at org.apache.spark.sql.DataFrameWriter$$anonfun$runCommand$1.apply(DataFrameWriter.scala:668) INFO - at org.apache.spark.sql.DataFrameWriter$$anonfun$runCommand$1.apply(DataFrameWriter.scala:668) INFO - at org.apache.spark.sql.execution.SQLExecution$$anonfun$withNewExecutionId$1.apply(SQLExecution.scala:78) INFO - at org.apache.spark.sql.execution.SQLExecution$.withSQLConfPropagated(SQLExecution.scala:125) INFO - at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:73) INFO - at org.apache.spark.sql.DataFrameWriter.runCommand(DataFrameWriter.scala:668) INFO - at org.apache.spark.sql.DataFrameWriter.saveToV1Source(DataFrameWriter.scala:276) INFO - at org.apache.spark.sql.DataFrameWriter.save(DataFrameWriter.scala:270) INFO - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) INFO - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) INFO - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) INFO - at java.lang.reflect.Method.invoke(Method.java:498) INFO - at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244) INFO - at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357) INFO - at py4j.Gateway.invoke(Gateway.java:282) INFO - at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) INFO - at py4j.commands.CallCommand.execute(CallCommand.java:79) INFO - at py4j.GatewayConnection.run(GatewayConnection.java:238) INFO - at java.lang.Thread.run(Thread.java:750)
解决方案
- 匹配SSL版本:确保Spark Connector和Cassandra服务端使用的SSL/TLS版本一致,可通过设置
spark.cassandra.connection.ssl.protocol参数指定版本,比如TLSv1.2,需和Cassandra配置的版本对应。 - 验证Cassandra SSL状态:检查Cassandra的
cassandra.yaml配置文件,确认client_encryption_options下的enabled设为true,且已正确配置证书文件路径。 - 补全Spark SSL配置:除了开启SSL,还需配置信任库相关参数:
spark.cassandra.connection.ssl.trustStore.path=/path/to/truststore.jks spark.cassandra.connection.ssl.trustStore.password=your-truststore-password - 确认连接端口:Cassandra默认SSL端口为9142,若Spark连接的是普通端口9042但Cassandra仅在SSL端口开启加密,会导致握手失败,需修改Spark连接端口为9142。
- 检查证书有效性:确保信任库中的证书是Cassandra服务端使用的有效证书,未过期且格式正确(如JKS格式)。
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

