Dataproc用Spark JDBC连Cloud SQL遇ClassNotFoundException求助排查
我之前在Dataproc上用Spark JDBC连接Cloud SQL时也碰到过一模一样的ClassNotFoundException,折腾了好一会儿才搞定,给你分享几个排查和解决的方向:
1. 先确认Fat Jar里真的包含了SocketFactory类
很多时候打包看起来成功了,但其实依赖没被正确打进Jar里。你可以用下面的命令检查你的Fat Jar内容:
jar tf your-spark-job-fatjar.jar | grep com.google.cloud.sql.mysql.SocketFactory
如果没有输出任何结果,说明这个类根本没在Jar里,问题直接出在打包环节。
2. 检查Maven打包插件的配置
如果你用的是maven-shade-plugin或者maven-assembly-plugin,要确保它们把mysql-socket-factory的依赖完整包含进去,尤其是服务配置文件:
示例:Maven Shade插件配置
Shade插件需要合并META-INF/services下的配置文件,否则SocketFactory无法被正确加载:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <transformers> <!-- 合并服务配置,避免SocketFactory找不到 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>your.main.class.full.path</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
示例:Maven Assembly插件配置
如果用Assembly,要在依赖集合里明确包含socket factory:
<assembly> <id>fatjar</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <outputDirectory>/</outputDirectory> <useProjectArtifact>true</useProjectArtifact> <unpack>true</unpack> <scope>runtime</scope> <includes> <include>com.google.cloud.sql:mysql-socket-factory-connector-j-8</include> <include>mysql:mysql-connector-java</include> </includes> </dependencySet> </dependencySets> </assembly>
3. 绕过Fat Jar,直接在Dataproc作业提交时指定依赖
如果打包实在有坑,可以试试不把socket factory打进Fat Jar,而是在提交Spark作业时用--jars参数单独指定这个依赖:
gcloud dataproc jobs submit spark \ --cluster your-cluster-name \ --region your-region \ --jars gs://your-bucket/mysql-socket-factory-connector-j-8-1.0.15.jar,gs://your-bucket/your-spark-job.jar \ --class your.main.class.full.path
这样Dataproc会单独加载这个依赖Jar,避免类加载优先级冲突的问题。
4. 检查版本兼容性
确保你的mysql-connector-java版本和mysql-socket-factory版本匹配:
mysql-socket-factory-connector-j-8对应MySQL Connector/J 8.x版本,如果你的项目里用的是5.x驱动,会出现类不兼容或者找不到的情况,把驱动版本统一成8.x即可。
5. 最后确认JDBC URL格式
虽然这不是类找不到的直接原因,但顺便检查下cloudSqlInstance的格式是否正确,应该是[GCP项目ID]:[区域]:[Cloud SQL实例名],比如my-gcp-project:us-central1:my-sql-instance。
按照上面的步骤排查下来,应该能解决ClassNotFoundException的问题。
内容的提问来源于stack exchange,提问作者ganesh_patil

