从 GCP 连接到 Azure SQL 时出现 NoClassDefFoundError com/microsoft/aad/adal4j/AuthenticationException

Posted

技术标签:

【中文标题】从 GCP 连接到 Azure SQL 时出现 NoClassDefFoundError com/microsoft/aad/adal4j/AuthenticationException【英文标题】:NoClassDefFoundError com/microsoft/aad/adal4j/AuthenticationException while connecting to Azure SQL from GCP 【发布时间】:2022-01-14 06:31:03 【问题描述】:

我在 GCP 的 data_proc 上有我的 spark 项目,在 spark 提交上运行驱动程序。 当我尝试连接到 Azure SQL DB 时,它会引发以下异常:

20:39:15 DOCKER: Exception in thread "main" java.lang.NoClassDefFoundError: com/microsoft/aad/adal4j/AuthenticationException
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.getFedAuthToken(SQLServerConnection.java:3609)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.onFedAuthInfo(SQLServerConnection.java:3580)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.processFedAuthInfo(SQLServerConnection.java:3548)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onFedAuthInfo(tdsparser.java:261)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:103)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.sendLogon(SQLServerConnection.java:4290)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:3157)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.access$100(SQLServerConnection.java:82)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:3121)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2026)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1687)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1528)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:866)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnectionInternal(SQLServerDataSource.java:968)
20:39:15 DOCKER:    at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnection(SQLServerDataSource.java:69)

以下是组件的版本:

数据过程:1.5 adal4j:1.6.7 azure-sqldb-spark:1.0.2

身份验证是通过 Active Directory 进行的。 同样的事情在本地有效,但在 dataproc 中无效。 感谢任何帮助!

【问题讨论】:

你是把所有的库都打包成一个 uberjar 了吗? @AlexOtt :是的,它是一个胖 jar,它具有所有依赖项,但我觉得在运行时 dataproc 使用了其他版本的 jar 您实际上是如何提交 spark 作业的?你看到this related SO question了吗? @jccampanero :我正在使用自定义图像(差别不大)来创建集群。我什至删除了初始化脚本并在那之后创建了集群。 spark spark提交是香草味的,我指定了集群、jar、区域和属性 非常感谢@SashiKant 的反馈。那么您的图像可能包含某种导致问题的依赖性。拜托,你能回顾一下这个Github issue,尤其是this answer吗?它表明应该删除的 hadoop 纱线库中存在旧的 mssql 服务器依赖项。此外,虽然适用于数据块,但我认为问题中提供的一些建议可能很有价值。我希望它有所帮助。 【参考方案1】:

看来您正在使用 Docker。如果是这样,您需要确保 adal4j.jar 包含在驱动程序 Docker 容器中,或者它是通过 Spark 提交命令中的 --jars 标志添加的:

gcloud dataproc jobs spark submit \
  --cluster-name $CLUSTER_NAME \
  . . . \
  --jars adal4j.jar

作为参考,请参阅如何在 Spark 中管理 Java 依赖项:https://cloud.google.com/dataproc/docs/guides/manage-spark-dependencies

【讨论】:

感谢您的回答,--jars 选项使用“HCFS URI”我如何在我的 dataproc 中找到它?我将尝试添加 Maven 阴影插件。我正在使用dataproc 1.5,我们怎么知道那里使用的hadoop版本,我们可以升级它,正如所说的这个问题在hadoop3中得到解决。您能否分享一下hadoop的相对库位置,从哪里覆盖jar? HCFS URI 表示您可以将此 jar 上传到某个 GCS 存储桶中并从那里引用它:--jars=gs://$BUCKET/adal4j.jar。也就是说,gcloud CLI 中的--jars 标志也支持本地文件(它会为您将本地文件上传到集群暂存 GCS 存储桶)。 在你提供的链接中,它说即使我们在 spark 提交期间指定了 jar,它仍然会优先考虑 hadoop 所指的库,你能帮我解决 hadoop 的路径吗? s 依赖存储在本地? 例如,如果您想让某个库在集群范围内可用于所有 Spark 作业,那么您需要编写一个init action,以便在所有集群创建期间将其下载到/usr/lib/spark/jars/目录集群节点。如果您的库将在 /usr/lib/spark/jars/ 中的所有集群节点上可用,则您无需在 Spark 作业提交期间显式包含它,但您真正需要的情况并不常见。 感谢 Igor,用 shade 插件解决了这个问题【参考方案2】:

如果您将作业代码打包为包含所有依赖项的胖 jar,并且您将 submitted it appropriately 打包到 Dataproc 集群,即使这样您仍面临错误,问题的一个可能原因是与SQL Server 驱动程序库存在于某处。正如我在评论中所指出的,尽管在不同的上下文中,类似的行为在几个 Github 问题中报告,例如 this 或 this other。

除了尝试删除冲突库之外,我不知道是否适用于您的用例 - 可能不是数据库驱动程序 - 但也许您可以尝试将 SQL Server 代码重新定位到不同的包并改用该包。

该方法在the GCP Dataproc documentation、for instance 中描述,使用Maven shade plugin。

【讨论】:

非常感谢JC,用shade插件解决了 欢迎您@SashiKant。我很高兴听到答案中提出的解决方案很有帮助。

以上是关于从 GCP 连接到 Azure SQL 时出现 NoClassDefFoundError com/microsoft/aad/adal4j/AuthenticationException的主要内容,如果未能解决你的问题,请参考以下文章

将 Azure 数据连接到 Power BI 的 oData 时出现问题

使用连接字符串通过 WCF 服务建立与 Azure SQL 数据库的连接时出现问题

从 Java 连接到 SQL Server 2016 时出现 EXCEPTION_ACCESS_VIOLATION

尝试连接到 Cloud SQL 实例时出现 403

将 VWD Express 2008 连接到 SQL Server Express 2005 时出现问题

将 spark 应用程序连接到远程 sql 服务器时出现 jdbc 连接超时错误