IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Spark on yarn运行时Jar包加载踩坑经历 -> 正文阅读

[大数据]Spark on yarn运行时Jar包加载踩坑经历

小菜鸟的个人博客已经正式上线且对外开放啦…

博客访问地址小菜鸟的大梦想

欢迎各位同学扫码关注本人公众号 ↓↓↓ 更多优质内容将 首发 公众号
在这里插入图片描述


前言

本文起因于近段时间在做的项目,百亿级数据的存储与实时检索。项目主要采用HBase存储全量数据,Elasticsearch作为二级索引库,数据入库采用Spark批量写入,最终数据通过微服务平台API接口对外提供实时线上访问。

  • HBase端采用saveAsNewHadoopFile算子生成HFile文件,然后通过HBase自带bulk load方式进行加载
  • Elasticsearch端采用批量bulk方式写入数据

具体方案由于工作原因,不便透漏,此处不再详细叙述,感兴趣的可以至 本人博客 留言板 或者 随心聊 模块私信本人。

下面主要叙述项目上线后 Spark on yarn 运行时 Jar 包加载异常的解决方案。

生产异常报错

由于表入库时需要读取 Mysql 数据库当前表的配置信息,因此项目中添加了 Mysql 驱动的依赖,测试环境从开发到上线均正常运行。但一上生产通过调度工具调用起来直接就报错,我们这上线换版出现问题是比较严重的,所以当时还是小小惊了一下的,然后抓紧时间通过电话排查问题(此时我已经回家了)。

1.查看运行日志

// 主要日志
java.sql.SQLException: No suitable driver

后续日志省略...

很明显就是找不到合适的驱动,明显是挺明显,但是很懵逼…
明显的是驱动加载的问题,懵逼的是测试环境运行居然顺畅无阻。

懵逼归懵逼但还是要抓紧时间解决问题,中间又让同事在测试环境同步进行排查,并解压检查上线包里的mysql驱动是否package进去了,但是无疾而终。由于连接mysql这块的代码不是我开发的,具体情况也不太清楚,只知道测试环境跑的没有问题。没办法,只好想着先通过临时指定驱动包(submit提交时通过参数指定)的方式进行解决,但通过网上查到的方式,似乎有的可以有的不行,而我们这的生产环境又不让做任何尝试性的测试操作(很扯dan)。由于不能百分百的确定可以,所以这种方式打算暂时放弃。后来想了想干脆直接把mysql驱动包放到${SPARK_HOME}/jars目录下得了,这样在运行时肯定是会被加载到的。结果自然是可以运行了,但是对于源代码运行异常,还得需要进一步排查。

第二天到公司后,在测试环境开始分析可以运行的原因,最后发现测试环境每台服务器 ${JAVA_HOME}/jre/lib/ext 目录下都存在 mysql-jdbc 的驱动包(不知道哪位大佬先前埋下的坑,目前也无从查起),把驱动包手动移除之后再重新跑Spark任务,也开始报和生产一样的错,而生产环境后来检查了环境之后,发现JAVA_HOME目录下是没有这个包的。所以就可以解释生产异常而测试通过了。

环境不一致归不一致,但是理论上项目中已经加载了mysql驱动的依赖,并且也确定发版后驱动包也包含在内,那么还出现运行时加载异常的问题,就大致可以定位以下两种情况:

  • 读取mysql部分的代码问题(代码中未明确指定Driver)
  • spark-submit脚本提交任务时参数(jar包加载)问题

Spark on yarn加载的jar

在进行试验之前先了解下 spark on yarn 运行时会加载的jar包:

  • spark-submit中指定的–jars
  • $SPARK_HOME/jars下的jar包
  • yarn提供的jar包
  • spark-submit通过参数spark.driver/executor.extraClassPath指定的jar包

spark-submit中指定jar

当使用如下的脚本提交应用时,会将应用本身的jar以及–jar指定的jar包上传到集群中。

./bin/spark-submit \
 --class org.apache.spark.examples.SparkPi \ 
 --jars a.jar,b.jar,c.jar \
 http://path/to/examples.jar \

–jar是以逗号分隔的jar包列表,不支持直接使用目录。
–jar上传的包会包含在Driver和Executor的classpath中

$SPARK_HOME/jars下的jar包

提交应用时,会将$SPARK_HOME/jars下的所有jar包打成一个zip包,上传到集群中。“打zip上传”这个操作会在每次提交应用时执行,会有一点的性能损耗。

yarn提供的jar包

在yarn-site.xml中会配置yarn.application.classpath,包含hadoop相关的一些包,这些包也会在应用提交的时候被加载。

<property>
	<name>yarn.application.classpath</name>
	<value>$HADOOP_CLIENT_CONF_DIR,$HADOOP_COMMON_HOME/*,$HADOOP_COMMON_HOME/lib/*,$HADOOP_HDFS_HOME/*,$HADOOP_HDFS_HOME/lib/*,$HADOOP_YARN_HOME/*,$HADOOP_YARN_HOME/lib/*</value>
</property>

通过参数指定的jar包

spark.executor.extraClassPath #显式地将jar包注册到executor的classpath中
spark.driver.extraClassPath #与executor配置项同理
spark.driver.userClassPathFirst=true
spark.executor.userClassPathFirst=true

通过extraClassPath指定jar包的方式和之前通过 --jars 差不多,只不过extraClassPath可以通过指定目录的方式来指定,如/cdh/jars/*。
另外extraClassPath可以通过配置userClassPathFirst来保证用户指定的jar包先被加载,这在解决冲突时是作用很大的。

实验测试结果

在明确了上一部分的各种加载方式之后,针对驱动包的加载进行了测试,其结果如下:

spark-submit主要测试参数

--jars ${jdbcpath}
--driver-class-path ${jdbcpath}
--conf spark.driver.extraClassPath=${jdbcpath}
--conf spark.executor.extraClassPath=${jdbcpath}

代码读取mysql数据库

val url: String = "jdbc:mysql://IP:port/dbName"
val userPass: String = "user=xxx&password=xxx"

//方式一:不显示指定Driver
spark.read.jdbc(s"$url?$userPass", "tableName", new Properties())

//方式二
val properties: Properties = new Properties()
properties.put("driver", "com.mysql.jdbc.Driver")
properties.put("user", "xxx")
properties.put("password", "xxx")
spark.read.jdbc(url, "tableName", properties)

//方式三
spark.read.format("jdbc")
  .option("url", url)
  .option("driver", "com.mysql.jdbc.Driver")
  .option("user", "xxx")
  .option("password", "xxx")
  .option("dbtable", "tableName")
  .load()

最终测试结论

1. 驱动放入 SPARK_HOME/jars 或者 JAVA_HOME/jre/lib/ext 目录
不用重启任何服务,代码中不显示指定Driver,且spark-submit不用额外指定任何参数可以运行;
但不建议将驱动包放至JAVA_HOME中,避免引起较为严重的冲突问题。

2. 代码中指定Driver
spark on yarn client 和 cluster 模式提交任务均可运行成功,且spark-submit中无需额外指定驱动包相关路径参数。

3. 代码中不指定Driver
1) client模式提交

spark-submit提交需要显示指定以下参数,jdbcpath需设置为本地路径
--driver-class-path ${jdbcpath}
或
--jars ${jdbcpath}
--conf spark.driver.extraClassPath=${jdbcpath}
--conf spark.executor.extraClassPath=${jdbcpath}

jdbcpath 为 HDFS路径时 或 其它参数情况运行报错:java.sql.SQLException: No suitable driver

2) cluster模式提交

spark-submit提交指定以下参数,jdbcpath需设置为HDFS路径
--driver-class-path ${jdbcpath}
或
--jars ${jdbcpath}
--conf spark.driver.extraClassPath=${jdbcpath}
--conf spark.executor.extraClassPath=${jdbcpath}

jdbcpath 为 本地路径时 或 其它参数情况运行报错,YARN上报错日志:
Diagnostics:  User class threw exception: java.sql.SQLException: No suitable driver
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 11:59:18  更:2021-09-03 11:59:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:37:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码