sparkCluster模式提交方式
spark-submit脚本提交yarn-cluster模式,
首先由脚本,提交提交spark Application 到ResourceManager上,然后ResourceManager找到一个NodeManager启动ApplicationMaster进程,这时,我们的NodeManager就会启动一个ApplicationMaster进程,这个就相当于我们的Driver进程,我们的Driver进程不是在本地机器跑了,这时,我们的ApplicationMaster(Driver)会去找我们的ResourceManager,申请executor,分配container(内存+cpu),然后ApplicationMaster就会找到一个NodeManager申请启动executor,然后executor想ApplicationMaster进行反向注册
到这里为止,ApplicationMaster(Driver),就知道自己有哪些资源可以用(executor),然后就会去执行job,拆分stage,提交stage的task,进行task调度,分配到各个executor上面去执行
yarn-client和yarn-cluster的不同之处:
yarn-client模式,driver运行在本地机器上的;
yarn-cluster模式,deriver是运行在yarn集群上某个nodemanager节点上面的,
yarn-client会导致本地机器负责spark作业的调度,所以网卡流量会激增,yarn-cluster模式就没有这个问题
yarn-client的driver运行在本地,通常来说本地机器跟yarn集群都不会是在一个机房的,所以说性能可能不是特别好,
yarn-cluster,driver是跟yarn集群运行在一个机房内,性能上也会好一点
实战经验,碰到的yarn-cluster的问题:
有的时候,运行一些包含了spark sql的spark作业,可能会碰到yarn-clent模式下,可以正常提交运行,yarn-cluster模式下,可能是无法提交运行的,会报出JVM的PermGen(永久代)的内存溢出,OOM
yarn-client模式下,driver是运行在本地机器上的,spark使用的JVM的PermGen的配置,是本地的spark-class文件(spark客户端是默认有配置的),JVM的永久代的大小是128M,这个是没有问题的,但是呢,在yarn-cluster模式下,driver是运行在yarn集群的某个节点上的,使用的是,没有经过配置的默认设置(PermGen的大小),82M。
spark-sql,它的内部是要进行很复杂的SQL语义解析,语法树的转换等等,特别复杂,在这种复杂的情况下,如果说你的sql本身特别复杂的话, 很可能会比较导致性能的消耗,内存的消耗,可能对PermGen永久代的占用会比较大。
所以,此时,如果对永久代的占用需求,超过了82M,但是呢又在128M以内,就会出现如上述的问题,yarn-client模式下,默认是128M,这个还可以运行,如果在yarn-cluster模式下,默认是82M,就有问题了,会报出PermGen Out of Memory error log。
如何解决这种问题,?
既然是JVM的PermGen永久代内存溢出,那么就是内存不够用,就给yarn-cluster模式下,driver的PermGen多设置一些
spark-submit脚本中,加入一下配置
--conf spark.driver.extraJavaOptions="-XX:PermSize=128M -XX:MaxPermSize=256M"
这个就设置了driver的永久代大小,默认是128M,最大是256M,这样就基本可以保证以上问题的出现
spark sql,sql,要注意,一个问题
sql,有大量的or语句,当达到or语句有成千上百的时候,此时可能会出现一个driver端的JVM stack overFlow,Jvm栈内存溢出的问题
JVM栈内存溢出,基本上就是由于调用的方法层级过多,因为产生了大量的,非常深的,超过了JVM栈深度的限制的,递归,递归方法,我们的猜测,spark sql ,有大量or语句的时候,spark sql内部源码中,在解析sql,不如转换成语法树,或者进行执行计划的生成的时候,对or处理是递归,or特别多就会发生大量的递归
就会发生JVM stack Memory overflow,栈内存溢出