Dataproc Debian虚拟机中PySpark DataFrame.show()抛SSL异常求助
问题:Dataproc集群中Spark JDBC读取SQL Server时SSL连接重置异常
我目前使用GCP及Dataproc,刚接触Apache Spark、PySpark与Debian虚拟机。尝试在Dataproc集群(Debian 10,Hadoop 3.2、Spark 3.1.3)中复现本地(Win10+VSCode+Spark3.3.1)可正常运行的Spark作业:通过JDBC驱动(mssql-jdbc-11.2.1.jre8.jar)从SQL Server导入数据到Spark DataFrame。
在Debian虚拟机中,SparkSession.read()可正常执行(删除$JAVA_HOME/jre/lib/security/java.security后解决了之前的SSL异常),但调用dataFrame.show()或dataFrame.write()时会抛出SSL连接重置异常,而dataFrame.printSchema()可正常运行。具体报错信息如下:
dataFrame.show(5) 22/11/17 13:08:16 WARN org.apache.spark.sql.catalyst.util.package: Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.sql.debug.maxToStringFields'. 22/11/17 13:09:57 WARN org.apache.spark.scheduler.TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0) (cluster-name.internal executor 2): com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "Connection reset ClientConnectionId:". at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:3806) at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1906) at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:3329) at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2950) at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2790) at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1663) at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1064) at org.apache.spark.sql.execution.datasources.jdbc.connection.BasicConnectionProvider.getConnection(BasicConnectionProvider.scala:49) at org.apache.spark.sql.execution.datasources.jdbc.connection.ConnectionProvider$.create(ConnectionProvider.scala:77) at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$.$anonfun$createConnectionFactory$1(JdbcUtils.scala:62) at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD.compute(JDBCRDD.scala:272) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373) at org.apache.spark.rdd.RDD.iterator(RDD.scala:337) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373) at org.apache.spark.rdd.RDD.iterator(RDD.scala:337) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:52) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:373) at org.apache.spark.rdd.RDD.iterator(RDD.scala:337) at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90) at org.apache.spark.scheduler.Task.run(Task.scala:131) at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$3(Executor.scala:505) at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1439) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:508) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:750) Caused by: java.io.IOException: Connection reset ClientConnectionId:700149ae-3483-4315-8c2e-de1bc11ce6b3 at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.readInternal(IOBuffer.java:974) at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.read(IOBuffer.java:961) at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:1207) at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.read(IOBuffer.java:1194) at org.conscrypt.ConscryptEngineSocket$SSLInputStream.readFromSocket(ConscryptEngineSocket.java:920) at org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:884) at org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:706) at org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:230) at org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:209) at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1795) ... 25 more
排查方向与解决思路
- 集群节点环境不一致:
SparkSession.read()和printSchema()仅在Driver端执行,只需验证连接、获取元数据;但show()/write()会触发Executor节点的实际数据拉取。你只修改了Driver节点的java.security文件,Executor节点的配置未同步,导致Executor端SSL握手失败。需用Dataproc初始化脚本批量修改所有节点的该文件,或手动同步配置到每个Executor。 - JDBC URL参数未适配集群环境:本地环境可能默认启用了某些SSL参数,集群环境需显式配置。可在JDBC URL中添加
encrypt=false(仅测试用,生产不推荐)跳过SSL验证,或添加trustServerCertificate=true信任服务器证书;同时确认SQL Server的TLS版本要求,添加sslProtocol=TLSv1.2指定兼容的协议版本。 - 驱动与版本兼容性问题:
mssql-jdbc-11.2.1.jre8.jar对应JDK8,需确认Dataproc集群的JDK版本是否匹配;另外Spark 3.1.3和3.3.1的JDBC实现有差异,可尝试降级驱动到适配Spark 3.1.x的版本(如mssql-jdbc 9.x系列)。提交作业时要通过--jars参数确保驱动包分发到所有Executor节点的classpath中。 - 网络与防火墙拦截:Executor节点可能无法访问SQL Server的SSL端口(默认1433),或GCP VPC防火墙、SQL Server端防火墙拦截了SSL握手数据包。检查Dataproc集群所在VPC的防火墙规则,确保集群IP段能访问SQL Server的地址和端口;同时确认SQL Server的白名单包含Dataproc节点的IP。
- Conscrypt SSL引擎兼容性问题:报错中出现
org.conscrypt.ConscryptEngineSocket,这是Dataproc默认的SSL引擎,可能与SQL Server的SSL握手逻辑不兼容。可在Spark配置中指定使用JDK默认SSL引擎,添加参数:spark.driver.extraJavaOptions="-Djavax.net.ssl.SSLContextFactory=sun.security.ssl.SSLContextFactoryImpl" spark.executor.extraJavaOptions="-Djavax.net.ssl.SSLContextFactory=sun.security.ssl.SSLContextFactoryImpl"
内容的提问来源于stack exchange,提问作者Cir02
相关产品推荐
相关产品推荐

