spark远程debug之调试spark on yarn 程序

spark远程debug之调试spark on yarn 程序,第1张

简介

由于spark有多种运行模式,远程调试的时候,虽然大体步骤相同,但是还是有小部分需要注意的地方,这里记录一下调试运行在spark on yarn模式下的程序。

环境准备

需要完好的Hadoop,spark集群,以便于提交spark on yarn程序。我这里是基于CDH的环境

步骤

1.随便写个spark程序,比如序列化一个集合,然后求和。然后使用maven打包,上传至集群。可以先提交运行一次,确保可以运行成功。

[root@kjtlxsvr5 bin]# ./spark-submit --class cn.spark.study.core.ParallelizeCollection --master yarn-cluster --num-executors 3 --executor-cores 2 --executor-memory 1G --driver-java-options "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787" /home/spark-study-scala-0.0.1-SNAPSHOT-jar-with-dependencies.jar

现在有两个办法可以解决这个问题。

第一个办法是节点少的话,通过修改上面IDEA远程主机地址来一个一个试。

第二办法可以精确知道ApplicationMaster在哪里:

①通过CDH进入yarn的应用程序界面

②然后点击进入该程序的详细信息界面,如下图就可以知道Applicationmaster在哪台NodeManager上:

③可以去该节点查看进程,的确有一个ApplicationMaster,然后在IDEA中修改为该远程主机地址,开始debug程序看源码吧!

        由于Spark程序是运行在JVM基础之上的,所以我们这一篇来讨论一下关于JVM的一些优化 *** 作。在开始JVM调优 *** 作之前,我们先通过一张图看一下JVM简单的内存划分情况。

        关于JVM内存的深入知识在这里不赘述,请大家自行对相关知识进行补充。好,说回Spark,运行Spark作业的时候,JVM对会对Spark作业产生什么影响呢?答案很简单,如果数据量过大,一定会导致JVM内存不足。在Spark作业运行时,会创建出来大量的对象,每一次将对象放入JVM时,首先将创建的对象都放入到eden区域和其中一个survivor区域中;当eden区域和一个survivor区域放满了以后,这个时候会触发minor gc,把不再使用的对象全部清除,而剩余的对象放入另外一个servivor区域中。JVM中默认的eden,survivor1,survivor2的内存占比为8:1:1。当存活的对象在一个servivor中放不下的时候,就会将这些对象移动到老年代。如果JVM的内存不够大的话,就会频繁的触发minor gc,这样会导致一些短生命周期的对象进入到老年代,老年代的对象不断的囤积,最终触发full gc。一次full gc会使得所有其他程序暂停很长时间。最终严重影响我们的Spark的性能和运行速度。

基于以上原因, 我们的第一个JVM优化点就是降低cache *** 作的内存占比 ;

        spark中,堆内存又被划分成了两块儿,一块儿是专门用来给RDD的cache、persist *** 作进行RDD数据缓存用的;另外一块儿,就是我们刚才所说的,用来给spark算子函数的运行使用的,存放函数中自己创建的对象。默认情况下,给RDD cache *** 作的内存占比是0.6,即60%的内存都给了cache *** 作了。但是问题是,如果某些情况下cache占用的内存并不需要占用那么大,这个时候可以将其内存占比适当降低。怎么判断在什么时候调整RDD cache的内存占用比呢?其实通过Spark监控平台就可以看到Spark作业的运行情况了,如果发现task频繁的gc,就可以去调整cache的内存占用比了。通过SparkConf.set("spark.storage.memoryFraction","0.6")来设定。

    我们第二个JVM优化点是 堆外内存和连接等待时长的调整 ;其实这两个参数主要是为了解决一些Spark作业运行时候出现的一些错误信息而进行调整的。下面我们来分别介绍一下这两个点。

1.堆外内存的调整

a) 问题提出

        有时候,如果你的spark作业处理的数据量特别特别大,几亿数据量;然后spark作业一运行就会出现类似shuffle file cannot find,executor、task lost,out of memory(内存溢出)等这样的错误。这是因为可能是说executor的堆外内存不太够用,导致executor在运行的过程中,可能会内存溢出;然后可能导致后续的stage的task在运行的时候,可能要从一些executor中去拉取shuffle map output文件,但是executor可能已经挂掉了,关联的blockmanager也没有了;所以可能会报shuffle  output file not found;resubmitting task;executor lost 这样的错误;最终导致spark作业彻底崩溃。

        上述情况下,就可以去考虑调节一下executor的堆外内存。也许就可以避免报错;此外,有时,堆外内存调节的比较大的时候,对于性能来说,也会带来一定的提升。

b) 解决方案:

--conf  spark.yarn.executor.memoryOverhead=2048

        在spark-submit脚本里面添加如上配置。默认情况下,这个堆外内存上限大概是300多M;我们通常项目中真正处理大数据的时候,这里都会出现问题导致spark作业反复崩溃无法运行;此时就会去调节这个参数,到至少1G或者更大的内存。通常这个参数调节上去以后,就会避免掉某些OOM的异常问题,同时呢,会让整体spark作业的性能,得到较大的提升。

2.连接等待时长的调整

a) 问题提出:

        由于JVM内存过小,导致频繁的Minor gc,有时候更会触犯full gc,一旦出发full gc;此时所有程序暂停,导致无法建立网络连接;spark默认的网络连接的超时时长是60s;如果卡住60s都无法建立连接的话,那么就宣告失败了。碰到一种情况,有时候报错信息会出现一串类似file id not found,file lost的错误。这种情况下,很有可能是task需要处理的那份数据的executor在正在进行gc。所以拉取数据的时候,建立不了连接。然后超过默认60s以后,直接宣告失败。几次都拉取不到数据的话,可能会导致spark作业的崩溃。也可能会导致DAGScheduler,反复提交几次stage。TaskScheduler,反复提交几次task。大大延长我们的spark作业的运行时间。

b) 解决方案:

--conf spark.core.connection.ack.wait.timeout=300

        在spark-submit脚本中添加如上参数,调节这个值比较大以后,通常来说,可以避免部分的偶尔出现的某某文件拉取失败,某某文件lost掉的错误。

总结:本文关于JVM的相关调优暂时先到这里,关于Spark中的JVM相关知识后面会在trouble shutting的时候还会继续介绍。后续还会不断更新关于Spark作业优化的一些其他方式,欢迎关注。

z小赵    Spark性能调优之JVM相关参数调整

之前一直纠结怎么在Eclipse下调试用Java编写的spark程序,这里给大家讲一下步骤。实际上,没有几步,但是在网络上面不好找,几乎没有这样的文章或者技术贴。

在Eclipse下调试spark程序时,通常会用两种错误,第一种是hadoop的winUtils.exe有问题,第二种是序列化问题,错误表现是akka连接不上。

工具/原料

winUtils.exe

spark

方法/步骤

设置环境变量:HADOOP_HOME,在windows下调试Eclipse时,并不需要在windows下安装hadoop,只需要配置一下环境变量就好了,然后HADOOP_HOME执行的位置的bin下要有winUtils.exe,设置环境变量的方式不用讲了吧!

在Eclipse项目中添加spark-assembly-1.4.1-hadoop2.4.0.jar,这里添加你需要的版本。

注意,不要使用spark的分散的jar包,这一点主要是maven时需要注意,因为maven时它会下载好多jar,这里会引进第二个问题,序列化问题,应该是scala的问题。

设置环境变量SPARK_CLASSPATH,这个环境变量不是必须的,你看一下你的服务器是不是设置了。

其实这一步和下面的一步本质作用是一样的,都是告诉spark依赖的jar,而告诉spark依赖jar的方法有两种,一种是设置环境变量,另一种是addJar方式。作者是这样认为,如果公用的jar,那么就通过设置环境变量的方式,如果是算法私有的jar,就通过addJar方式。

注意,环境变量SPAKR_CLASSPATH的值是unix方式,就是跟服务器设置的一样,不要用win的方式“”,为啥呢?作者认为,通过设置环境变量的方式时,在初始化spark上下文时,并没有分发jar到各个worker,所以需要指定jar在服务器的位置。(有问题的话,请留言,嘴拙)

addJar方式,上面讲过了。与环境变量的方式区别在于,驱动程序启动,初始化上下文时,需要分发jar到各个worker,所以针对私有的jar,最好使用addJar方式。

到了这里,应该全部配置完成了,如果我讲述的比较清晰的话,你应该可以随意调试了。

如果存在问题,请指正。如果有疑问,请留言。

END

注意事项

SPAKR_CLASSPATH,如果不知道怎么弄,那么就不要设置了,全用addJar方式


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11095282.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存