GCP Dataproc Serverless加载MS SQL JDBC驱动失败求助
我用Spring Boot编写了一个Java Spark作业,需要在启动Spark操作前调用MS SQL数据库获取配置属性/值。本地环境中,我通过在Spark额外类路径传入驱动类的方式可正常运行该作业。
我尝试通过Dataproc环境变量spark.dataproc.driverEnv.SPARK_EXTRA_CLASSPATH设置额外类路径,配置为SPARK_EXTRA_CLASSPATH=gs://XXXX/XXXX/mssql-jdbc-12.2.0.jre11.jar,日志中也显示了该路径,但仍出现错误:
Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver.
错误详情:
Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:318)
相关代码:
public DataSource getDataSource() { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); dataSourceBuilder.driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); dataSourceBuilder.username(config.getSqlUser()); dataSourceBuilder.password(config.getSqlPass()); dataSourceBuilder.url(config.getSqlUrl()); return dataSourceBuilder.build(); }
请问是否有无需创建自定义镜像,仅通过额外类路径将依赖库添加到默认容器中的解决方案?
以下几种方法可在不创建自定义镜像的前提下解决问题:
提交作业时用
--jars参数指定驱动
直接在提交Spark作业时,把MS SQL驱动的GCS路径和你的应用Jar包一起传入--jars参数,该参数会自动将Jar包添加到driver和executor的类路径中:gcloud dataproc jobs submit spark \ --cluster=你的集群名称 \ --class=你的主类全路径 \ --jars=gs://XXXX/XXXX/mssql-jdbc-12.2.0.jre11.jar,你的应用Jar包GCS路径 \ --region=你的集群区域多个Jar包用逗号分隔即可。
设置Spark专属类路径属性
在提交作业时直接配置spark.driver.extraClassPath和spark.executor.extraClassPath属性,明确指定驱动Jar包路径:gcloud dataproc jobs submit spark \ --cluster=你的集群名称 \ --class=你的主类全路径 \ --properties=spark.driver.extraClassPath=gs://XXXX/XXXX/mssql-jdbc-12.2.0.jre11.jar,spark.executor.extraClassPath=gs://XXXX/XXXX/mssql-jdbc-12.2.0.jre11.jar \ --jar=你的应用Jar包GCS路径 \ --region=你的集群区域这种方式绕过环境变量的加载时机问题,直接把驱动Jar包注入到Spark的类加载逻辑中。
通过初始化动作将驱动复制到集群本地类路径
如果集群长期需要使用该驱动,可以编写初始化脚本把GCS上的驱动Jar包复制到集群节点的/usr/lib/spark/jars目录(Spark默认扫描的类路径目录):- 编写初始化脚本
copy-mssql-driver.sh:#!/bin/bash gsutil cp gs://XXXX/XXXX/mssql-jdbc-12.2.0.jre11.jar /usr/lib/spark/jars/ - 创建集群时指定该初始化动作:
gcloud dataproc clusters create 你的集群名称 \ --region=你的集群区域 \ --initialization-actions=gs://你的脚本存储路径/copy-mssql-driver.sh
后续所有提交到该集群的Spark作业都会自动加载这个驱动Jar包。
- 编写初始化脚本
之前用spark.dataproc.driverEnv.SPARK_EXTRA_CLASSPATH不生效的原因是:该环境变量是设置给driver进程的系统环境变量,但Spark的类路径初始化逻辑可能在环境变量生效前就已完成,导致驱动类未被加载到正确路径。上面的方法都是直接针对Spark的类路径配置,能确保驱动Jar包被正确识别。
内容的提问来源于stack exchange,提问作者Baskar Gopal

