1.以源文件的源码形式交作业是啥意思?
2.Spark源码解析2-YarnCluster模式启动
3.Spark-Submit 源码剖析
4.document.form.submit()
以源文件的形式交作业是啥意思?
Spark作业提交方式一般有两种,一种是源码使用spark-submit脚本进行提交作业,另一种方式是源码使用rest api方式,但是源码有时候由于集群的安全原因可能无法使用rest api方式进行提交作业,但是源码由于业务需要的话我们可以直接调用SparkSubmit.main方法进行api方式提交作业。(当然也可以使用ProcessBuilder执行shell脚本提交)。源码玫瑰大厅H5源码除了通常两种情况,源码Spark其实还提供了API提交作业的源码方法。
1 调用SparkSubmit提交作业:
为了使用SparkSubmit#main方法方式提交作业,源码因此重点就是源码需要构造参数,我们可以根据spark-submit脚本源码进行构造参数,源码翻阅spark-submit源码不难发现最终调用的源码是spark-class脚本提交作业,spark-class脚本中最核心的源码代码如下:
exec "${ CMD[@]}"
因此只要我们弄清楚 "${ CMD[@]}"参数是什么就可以解决问题,最好的源码方法就是在spark-class脚本中添加echo 打印出来看看。打印结果如下:
/usr/local/jdk1.8.0_/bin/java -cp /home/daxin/bigdata/spark/conf/:/home/daxin/bigdata/spark/jars/*:/home/daxin/bigdata/hadoop/etc/hadoop/:/home/daxin/bigdata/hadoop/etc/hadoop/ -Xmx1g org.apache.spark.deploy.SparkSubmit --master yarn --class com.daxin.remote.debug.App wc.jar
由于我们提交的源码.ready源码作业是使用yarn调度,因此需要传入hadoop相关配置。如果使用yarn调度却没有传入hadoop配置文件的话此时会提示操作不到ResourceMangaer,即信息如下:
0.0.0.0/0.0.0.0:. Already tried 7 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=, sleepTime=1 SECONDS)
正常spark脚本提交作业时候hadoop等相关配置文件是通过classpath传入的,因此我们在classpath传入即可。
2:使用SPARK API提交作业。
参考文档:https://spark.apache.org/docs/latest/rdd-programming-guide.html#launching-spark-jobs-from-java--scala,内容比较简单就不描述了。
此处需要注意:
如果Spark提交作业和Spring boot的jar整合的话,使用-cp是启动不起来的,由于Spring打包插件比较特殊,jar内部的目录结构与一般的jar结构不一样,所以使用-cp 指定mainclass会提示无法找到类,对于该情况可以将-cp与-jar联合使用。
例如:
java -cp 普通.jar -jar springboot.jar
最后还需要注意的moveit源码就是:Linux权限问题,有时候可能因为classpath下面的配置文件没有权限读,因此也是会失败的,一定要确保有权限。
Spark源码解析2-YarnCluster模式启动
YARN 模式运行机制主要体现在Yarn Cluster 模式和Yarn Client 模式上。在Yarn Cluster模式下,SparkSubmit、ApplicationMaster 和 CoarseGrainedExecutorBackend 是独立的进程,而Driver 是独立的线程;Executor 和 YarnClusterApplication 是对象。在Yarn Client模式下,SparkSubmit、ApplicationMaster 和 YarnCoarseGrainedExecutorBackend 也是独立的进程,而Executor和Driver是对象。
在源码中,SparkSubmit阶段首先执行Spark提交命令,cordovaplugin 源码底层执行的是开启SparkSubmit进程的命令。代码中,SparkSubmit从main()开始,根据运行模式获取后续要反射调用的类名赋给元组中的ChildMainClass。如果是Yarn Cluster模式,则为YarnClusterApplication;如果是Yarn Client模式,则为主类用户自定义的类。接下来,获取ChildMainClass后,通过反射调用main方法的过程,反射获取类然后通过构造器获取一个示例并多态为SparkApplication,再调用它的start方法。随后调用YarnClusterApplication的start方法。在YarnClient中,kdl源码new一个Client对象,其中包含了yarnClient = YarnClient.createYarnClient属性,这是Yarn在SparkSubmit中的客户端,yarnClient在第行初始化和开始,即连接Yarn集群或RM。之后就可以通过这个客户端与Yarn的RM进行通信和提交应用,即调用run方法。
ApplicationMaster阶段主要涉及开启一个Driver新线程、AM向RM注册、AM向RM申请资源并处理、封装ExecutorBackend启动命令以及AM向NM通信提交命令由NM启动ExecutorBackend。在ApplicationMaster进程中,首先开启Driver线程,开始运行用户自定义代码,创建Spark程序入口SparkContext,接着创建RDD,生成job,划分阶段提交Task等操作。
在申请资源之前,AM主线程创建了Driver的终端引用,作为参数传入createAllocator(),因为Executor启动后需要向Driver反向注册,所以启动过程必须封装Driver的EndpointRef。AM主线程向RM申请获取可用资源Container,并处理这些资源。ExecutorBackend阶段尚未完成,后续内容待补充。
Spark-Submit 源码剖析
直奔主题吧:
常规Spark提交任务脚本如下:
其中几个关键的参数:
再看下cluster.conf配置参数,如下:
spark-submit提交一个job到spark集群中,大致的经历三个过程:
代码总Main入口如下:
Main支持两种模式CLI:SparkSubmit;SparkClass
首先是checkArgument做参数校验
而sparksubmit则是通过buildCommand来创建
buildCommand核心是AbstractCommandBuilder类
继续往下剥洋葱AbstractCommandBuilder如下:
定义Spark命令创建的方法一个抽象类,SparkSubmitCommandBuilder刚好是实现类如下
SparkSubmit种类可以分为以上6种。SparkSubmitCommandBuilder有两个构造方法有参数和无参数:
有参数中根据参数传入拆分三种方式,然后通过OptionParser解析Args,构造参数创建对象后核心方法是通过buildCommand,而buildCommand又是通过buildSparkSubmitCommand来生成具体提交。
buildSparkSubmitCommand会返回List的命令集合,分为两个部分去创建此List,
第一个如下加入Driver_memory参数
第二个是通过buildSparkSubmitArgs方法构建的具体参数是MASTER,DEPLOY_MODE,FILES,CLASS等等,这些就和我们上面截图中是对应上的。是通过OptionParser方式获取到。
那么到这里的话buildCommand就生成了一个完成sparksubmit参数的命令List
而生成命令之后执行的任务开启点在org.apache.spark.deploy.SparkSubmit.scala
继续往下剥洋葱SparkSubmit.scala代码入口如下:
SparkSubmit,kill,request都支持,后两个方法知识支持standalone和Mesos集群方式下。dosubmit作为函数入口,其中第一步是初始化LOG,然后初始化解析参数涉及到类
SparkSubmitArguments作为参数初始化类,继承SparkSubmitArgumentsParser类
其中env是测试用的,参数解析如下,parse方法继承了SparkSubmitArgumentsParser解析函数查找 args 中设置的--选项和值并解析为 name 和 value ,如 --master yarn-client 会被解析为值为 --master 的 name 和值为 yarn-client 的 value 。
这之后调用SparkSubmitArguments#handle(MASTER, "yarn-client")进行处理。
这个函数也很简单,根据参数 opt 及 value,设置各个成员的值。接上例,parse 中调用 handle("--master", "yarn-client")后,在 handle 函数中,master 成员将被赋值为 yarn-client。
回到SparkSubmit.scala通过SparkSubmitArguments生成了args,然后调用action来匹配动作是submit,kill,request_status,print_version。
直接看submit的action,doRunMain执行入口
其中prepareSubmitEnvironment初始化环境变量该方法返回一个四元 Tuple ,分别表示子进程参数、子进程 classpath 列表、系统属性 map 、子进程 main 方法。完成了提交环境的准备工作之后,接下来就将启动子进程。
runMain则是执行入口,入参则是执行参数SparkSubmitArguments
Main执行非常的简单:几个核心步骤
先是打印一串日志(可忽略),然后是创建了loader是把依赖包jar全部导入到项目中
然后是MainClass的生成,异常处理是ClassNotFoundException和NoClassDeffoundError
再者是生成Application,根据MainClass生成APP,最后调用start执行
具体执行是SparkApplication.scala,那么继续往下剥~
仔细阅读下SparkApplication还是挺深的,所以打算另外写篇继续深入研读~
document.form.submit()
å¾å¥æªçé®é¢ï¼åµåµãã被æ碰å°äºã
å¾ç®å,å°é¡µé¢ä¸å称为"submit"çæ§ä»¶æ¹ä¸ä¸å称就å¯ä»¥äº
æ¯å¦:
æä¸ä¸ªsubmitæé®ååå«submit
<input type="submit" name="submit" value="æ交"/>
ä½ æè¿ä¸ªå称æ¹ä¸ä¸
<input type="submit" name="submit1" value="æ交"/>
-------------------------------------------------------------------
è¿ä¸¤å¤©åå表æ°æ®æ¾ç¤ºçæ¶åï¼å ä¹è¢«"对象ä¸æ¯ææ¤å±æ§åæ¹æ³" çé误æ示æç¯æäºï¼ä¸¤ä¸ªå®å ¨ä¸æ ·çç¨åºï¼äºåæç¥éæ个åè¯ç大å°å
ä¸ä¸æ ·ï¼ï¼ç«ç¶ä¸ä¸ªæ¾ç¤ºæ£å¸¸ï¼ä¸ä¸ªå´é¢ç¹æ示åºéã
å¨ä¸è¬æ åµä¸ï¼åä¸ä¸ªè¡¨ååªè½è¢«æ交ç»åä¸ä¸ªå°åãä½å¨å®é webåºç¨ä¸ï¼æ们å¸æåä¸ä¸ªè¡¨åå¯ä»¥æ ¹æ®ç¨æ·çéæ©æ¥å®æä¸åçæä½ï¼å³è¡¨
åçååæ交ãæ¯å¦è¯´ï¼å¨ä¸ä¸ªç½ç«åå°ç¨æ·ç®¡çç³»ç»ä¸ï¼æéè¦å¯¹ä¸äºæ¶æçç¨æ·è¿è¡æ¹é解éï¼éå®ç¨æ·æè å é¤çæä½ï¼å½æä»select
ä¸éæ©å é¤ä¼åæ¶ï¼æ们å¸æ表åä¼æ交ç»è½è¿è¡å é¤çå¤çç¨åºï¼å½æ ä»select ä¸éæ©éå®ä¼åæ¶ï¼æ们å¸æ表åä¼ æ交å°éå®ä¼åçå¤
çç¨åºï¼è§£éä¼å ä¹å¦æ¤ãæ们æä¸æ¿æçå°åå«ä¸ºè¿ä¸ä¸ªåè½å»ºç«ä¸ä¸ªä¸åç页é¢ï¼èå ¶ä¸ä» ä» æ¯å¤çç¨åºä¸åã
å©ç¨å®¢æ·ç«¯JavaScriptçåè½ï¼æ们ç®åå¯ä»¥æä¸é¡¹åè½ç®åä¸ä¸ªçé¢å°±å¯ä»¥å®æï¼ä¸ä¸ªselectï¼å ¶ä¸æ¾ç½®è¦è¿è¡çæä½ï¼ä¸ä¸ªSubmitæé®(å ¶
å®ä¸ä¸ªæ®éçButtonä¹å¯ä»¥å®ç°ï¼)
<form action="?" method="post" enctype="application/x-www-form-urlencoded" name="listfrm" id="listfrm">
<label>
<select name="Action" size="1" id="Action">
<option value="delete">å é¤</option>
<option value="lock">å é¤</option>
<option value="unlock">å é¤</option>
</select>
</label>
<input name="Submit" id="Submit" type="submit" value="ç¡®å®" onclick="doPostBack(this.form,'?" />
</form>
è¿æ¯JavaScriptä¸doPostBackå½æ°çæºä»£ç ï¼å ¶ä¸ä¼ éçåæ°ä¸ºè¡¨å对象çå¼ç¨å表åçactionæ件å°å
function doPostBack(formObj,actionFile){
if(confirm("ç¡®å®è¦æ§è¡çæä½åï¼")){
formObj.action=actionFile;
formObj.submit();
return true;
}
return false;
}
è¿æ ·å¯ä»¥å¨ä¸ä¸ªè¡¨åä¸æ¾ä¸å¤ä¸ªButton,çè³æ¯è¿æ¥ï¼é½å¯ä»¥å®ç°åä¸ä¸ªè¡¨åçæ交ç»ä¸åçå¤çç¨åºã
å¨å表åå¤çæ¶è¦æ³¨æï¼
1ã表ååºè¯¥å å«name,aciton,methodè¿ä¸ä¸ªå¿ é¡»çå±æ§ï¼enctype,idè¿ä¸¤ä¸ªå±æ§å¯ä»¥æ ¹æ®éè¦å ä¸ï¼ä¸è¬æ¯å»ºè®®å ä¸ï¼è¡¨åä¸è¦åµå¥
2.document.form.actionä¸document.form.submit()ä¸å®ä¸è¦ææ··ï¼actionæ¯å±æ§ï¼submitæ¯æ¹æ³ï¼æ¹æ³ä¸è¦å¿è®°å ä¸å·¦å³æ¬å·ï¼è¿æ¯ä¸è¬æ°æç»å¸¸éå°çé®é¢ã
3.å¨ä¸ä¸ªå®æ´è¡¨åä¸ï¼ä¸åºæåå为actionæsubmitçæ ç¾ï¼å¦åå°ä¼äº§ç"对象ä¸æ¯ææ¤å±æ§åæ¹æ³"çieé误ãå¦ä»£ç "<input type='xxxx' name="action" >"æ"<input type='xxxx' name="submit" >" å¨è¡¨åä¸æ¯ä¸å 许åºç°ç,èActionåSubmitåæ¯å 许ç(ä¸é¢çç¨åºä»£ç å°±æ¯ç¨çæ¯è¿æ ·çåæ³)ï¼å 为JavaScriptæ¯åºå大å°å.