Spark Submit的ClassPath问题

栏目: 编程工具 · 发布时间: 7年前

内容简介:Spark Submit的ClassPath问题

需求场景: 我们的产品需要与客户的权限系统对接,即在登录时使用客户的认证系统进行认证。集成认证的方式是调用客户提供的jar包,调用 userServiceauthenticate 方法。同时,还需要在classpath中提供密钥的key文件。

从需求看,这个集成并不复杂,且客户也提供了较翔实的接口文档与示例案例,开发工作量非常小。唯一的阻碍是客户有安全要求,内部的Jar包及其他文件都不能拷贝出来,而我们的开发环境是不能连接客户内网的。客户提供的Jar包并没有通过Maven来管理,我们只能采用直接导入的方式。在我们的Scala项目中,可以直接将要依赖的jar包放在module的lib文件夹下,在使用sbt执行编译和打包任务时,会自动将lib下的jar包放入classpath中。

那么,需要解决的第一个问题是: 由于客户的jar包不能拷贝到我的开发环境中,该如何处理该依赖?

既然在开发环境下拿不到这个jar包,那就做一个mock包吧。幸而需要编写的代码仅仅牵涉到 ServiceConfigServiceManagerUserService 三个类以及这些类的少数方法。其中 ServiceConfig 提供了认证需要的属性值,并通过set方法进行设置。因为最终需要调用的其实是 UserServiceauthenticate 方法,只需要为其提供一个简单的实现,并定义好其他相关的类型与方法,保证编译能够通过即可。

第一个问题轻松解决。

由于我们使用了sbt assembly,并编写了对应的脚本来支持整个产品的打包工作,最终打包的结果是一个完整的mort.jar包。换言之,我们要依赖的外部Jar包也将被打包到最终的jar文件中。故而,第二个问题接踵而来: 既然程序代码与外部jar包都被打包到最终的部署包中,当我们将该包拷贝到客户的部署环境中后,该如何将之前的mock包替换为真正的实现呢?

实际上,sbt assembly并不会将所有依赖的外部包都装配到最终的部署包中,只要在sbt的依赖中添加provided,就能保证第三方依赖包不被包含进部署包中。因此,我们可以改写sbt脚本,当执行assembly时,排除这个mock包,这是首要解决的方案。方法是在build.sbt中添加如下脚本:

excludedJars in assembly := {
  val cp = (fullClasspath in assembly).value
  cp filter {_.data.getName == "customer_provided_mock.jar" }
}

部署包确实不再包含这个外部依赖包了,但是在部署时,我们还得将真实的jar包放入到部署环境的classpath中。然而事与愿违,当我们将真正的jar包放在本地的classpath中时,运行时却找不到这个jar包。问题出现在哪里?

原因在于我们的程序并非一个普通的 java 程序,而是一个spark application,部署环境则为集群环境,运行该程序是通过spark submit的方式,将部署包提交到spark的cluster manager。这就需要分析spark submit的工作原理,如下图所示:

Spark Submit的ClassPath问题

在集群部署模式下,Driver端通过spark-submit将spark application提交到集群,然后分发到Job到Worker节点。我们系统的主程序入口为com.bigeyedata.mort.Main,程序的运行是通过spark-submit去调用部署包的Main,即在spark driver下运行,而非在本地通过java启动虚拟机执行mort.jar。

这就是在本地设置classpath不生效的根本原因。

我注意到spark-submit提供了--jar参数,除了spark application这个jar包之外的其他jar包,都可以通过这个参数指定包,从而将其自动传送给集群。注意,若--jar指定了多个jar包,则通过分隔符 , 分隔,这与--driver-class-path的分隔符不同,后者使用 : 。因此,我修改了启动程序的脚本,将其设置为:

exec $SPARK_HOME/bin/spark-submit \
--class com.bigeyedata.mort.Main \
--driver-class-path $MORT_HOME/libs/*.jar \
--master yarn-client \
--deploy-mode cluster \
--jars /appcom/mort/thirdparty_jars/customer_provided.jar \
--queue queue_0100_01 \
$MORT_HOME/mort.jar > $MORT_HOME/mort.log 2>&1

还有一个问题需要解决: 如何放置用户认证需要的密钥key文件?

该文件仍然不能作为内嵌的资源文件打包到部署包中。因为这个文件的内容需要区分测试环境和生产环境。在部署到生产环境中时,需要替换为另一个key文件。客户的文档说明,需要将该文件(不是jar文件)放到运行的classpath中。

解决办法如前,仍然不能直接将key文件放入到本地的classpath中,而是利用spark-submit的--files参数。故而需要在前面的脚本中,为spark-submit添加如下内容:

--files /appcom/mort/thirdparty_jars/clientKey.pk \

三个问题给我制造了一定的麻烦,尤其是第二个问题的解决,又让我温习了spark submit的工作原理,了解相关参数的作用。虽然花费了一些时间,但问题的解决还是颇有价值的。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Message Service API Tutorial and Reference

Java Message Service API Tutorial and Reference

Hapner, Mark; Burridge, Rich; Sharma, Rahul / 2002-2 / $ 56.49

Java Message Service (JMS) represents a powerful solution for communicating between Java enterprise applications, software components, and legacy systems. In this authoritative tutorial and comprehens......一起来看看 《Java Message Service API Tutorial and Reference》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换