基于AWS EMR Serverless的Spark JDBC连接Oracle 19c遇连接重置错误求助
Connection reset错误 核心问题定位方向
从你提供的错误java.sql.SQLRecoverableException: IO Error: Connection reset, Authentication lapse 0 ms来看,大概率是SSL协商失败、驱动依赖缺失或Spark配置冲突导致的,以下是针对性的排查和修复方案:
1. 修复Spark配置中的参数冲突
你的sparkSubmitParameters中重复设置了spark.driver.extraJavaOptions和spark.executor.extraJavaOptions,后设置的参数会覆盖前面的,导致-Djavax.net.debug=all被丢弃,无法获取完整的SSL调试日志。请合并所有JVM参数:
--conf spark.driver.extraJavaOptions="-Djavax.net.debug=all -Djava.security.egd=file:/dev/./urandom -Dsecurerandom.source=file:/dev/./urandom" --conf spark.executor.extraJavaOptions="-Djavax.net.debug=all -Djava.security.egd=file:/dev/./urandom -Dsecurerandom.source=file:/dev/./urandom"
保留-Djavax.net.debug=all可以输出详细的SSL握手日志,帮助定位连接重置的具体阶段。
2. 补充Oracle JDBC驱动的依赖JAR
ojdbc10/11仅包含核心JDBC逻辑,处理SSL连接和认证时需要额外的依赖包:
oraclepki.jarosdt_core.jarosdt_cert.jar
将这些JAR上传到同一个S3路径,更新spark.jars配置:
--conf spark.jars=s3://xxxxxxx/emr-serverless/ojdbc10-19.15.0.0.1.jar,s3://xxxxxxx/emr-serverless/oraclepki.jar,s3://xxxxxxx/emr-serverless/osdt_core.jar,s3://xxxxxxx/emr-serverless/osdt_cert.jar
这些包可以从Oracle官方驱动包(如ojdbc10-full.tar.gz)中提取。
3. 优化Oracle JDBC URL参数
在JDBC URL中添加SSL相关参数,强制指定SSL版本和加密套件,避免协商失败:
jdbc:oracle:thin:@//<host>:<port>/<service_name>?ssl=true&sslVersion=TLSv1.2&oracle.net.ssl_cipher_suites=(TLS_RSA_WITH_AES_256_CBC_SHA256)
如果Oracle未启用SSL,尝试添加disableOob=true参数,解决可能的OutOfBand数据传输问题:
jdbc:oracle:thin:@//<host>:<port>/<service_name>?disableOob=true
4. 排查Oracle端的连接日志
登录Oracle服务器,查看listener.log(通常路径为$ORACLE_HOME/diag/tnslsnr/<hostname>/listener/trace/listener.log),检查是否有连接被拒绝的具体原因,比如:
- SSL版本不兼容
- 客户端认证失败
- 防火墙拦截特定加密套件
5. 简化Spark作业进行测试
暂时关闭动态分配,使用单Executor测试,排除资源调度导致的连接问题:
--conf spark.dynamicAllocation.enabled=false --conf spark.executor.instances=1
编写极简的Spark作业,仅执行连接测试:
import org.apache.spark.sql.SparkSession object OracleTest { def main(args: Array[String]): Unit = { val spark = SparkSession.builder.appName("OracleConnectionTest").getOrCreate() val df = spark.read.format("jdbc") .option("url", "jdbc:oracle:thin:@//<host>:<port>/<service_name>") .option("dbtable", "<test_table>") .option("user", "<username>") .option("password", "<password>") .option("driver", "oracle.jdbc.OracleDriver") .load() df.show(10) spark.stop() } }
6. 验证Java版本与驱动的兼容性
Java 17推荐使用ojdbc11(19.15+版本),替换ojdbc10后重新测试,确保驱动版本与Java runtime完全匹配。
内容的提问来源于stack exchange,提问作者eduardollopes

