You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 22:35:22