sparkR原理
sparkR在spark2.0里面,RDD后端代码位于org.apache.spark.rdd中,R语言相关的位于org.apache.spark.api.r中。
从入口开始,./bin/sparkR里面只有四句话,调用的是这个
exec "$SPARK_HOME"/bin/spark-submit sparkr-shell-main "$@"
spark-submit里面是个一句话的shell脚本
exec "$SPARK_HOME"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"
好了,入口是org.apache.spark.deploy.SparkSubmit这个类,该类中的main方法中调用具体方法
case SparkSubmitAction.SUBMIT => submit(appArgs) /**
* Submit the application using the provided parameters. *
* This runs in two steps. First, we prepare the launch environment by setting up
* the appropriate classpath, system properties, and application arguments for
* running the child main class based on the cluster manager and the deploy mode.
* Second, we use this launch environment to invoke the main method of the child * main class.
*/
private def submit(args: SparkSubmitArguments): Unit = {
submit方法准备classpath、系统属性、运行参数,然后按照这些调用下面的方法运行
runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
该方法主要两步,第一步调用下面方法进行准备
val (childArgs, childClasspath, sysProps, childMainClass) = prepareSubmitEnvironment(args)
第二部会调用
runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
进行执行。
在第一步中将sparkR的R相关代码打包成zip文件,然后设置将要运行的主类
如果是SPARKR-SHELL则调用org.apache.spark.api.r.RBackend
如果是纯粹client模式,则调用org.apache.spark.deploy.RRunner,其调用形式如下,例如
Usage: RRunner <main R file> [app arguments]
sun.java.command=com.aliyun.odps.cupid.runtime.Main --class org.apache.spark.deploy.RRunner --primary-r-file testOdpsRdd.R --arg testOdpsRdd.R
RBackend基于netty用来在R和java之间的通讯
Runner里面会调用启动RBackend,然后启动processBuilder去执行R脚本,也就是这句话:
new ProcessBuilder(Seq(rCommand, rFileNormalized) ++ otherArgs)
如何让spark worker识别sparkR代码呢?在R语言中变量R_PROFILE_USER ,用来初始化R运行环境,sparkR相关代码被打包提交到计算集群以后,在计算节点上面首先设置这个数值指向到初始化脚本${SPARK_HOME}/sparkr/SparkR/profile/general.R,这个脚本中识别路径,并且把解压后sparkR的代码安装到当前R环境中。下面是其代码
.First <- function() {
packageDir <- Sys.getenv("SPARKR_PACKAGE_DIR")
.libPaths(c(packageDir, .libPaths()))
Sys.setenv(NOAWT=1)
}
下面的代码来自于prepareSubmitEnvironment
// In YARN mode for an R app, add the SparkR package archive to archives
// that can be distributed with the job
if (args.isR && clusterManager == YARN) {
val rPackagePath = RUtils.localSparkRPackagePath
if (rPackagePath.isEmpty) {
printErrorAndExit("SPARK_HOME does not exist for R application in YARN mode.")
}
val rPackageFile = RPackageUtils.zipRLibraries(new File(rPackagePath.get), SPARKR_PACKAGE_ARCHIVE)
if (!rPackageFile.exists()) {
printErrorAndExit(s"$SPARKR_PACKAGE_ARCHIVE does not exist for R application in YARN mode.")
}
val localURI = Utils.resolveURI(rPackageFile.getAbsolutePath)
// Assigns a symbol link name "sparkr" to the shipped package.
args.archives = mergeFileLists(args.archives, localURI.toString + "#sparkr")
}
// If we're running a R app, set the main class to our specific R runner if (args.isR && deployMode == CLIENT) {
if (args.primaryResource == SPARKR_SHELL) {
args.mainClass = "org.apache.spark.api.r.RBackend"
} else {
// If a R file is provided, add it to the child arguments and list of files to deploy. // Usage: RRunner <main R file> [app arguments]
args.mainClass = "org.apache.spark.deploy.RRunner"
args.childArgs = ArrayBuffer(args.primaryResource) ++ args.childArgs args.files = mergeFileLists(args.files, args.primaryResource)
}
}
if (isYarnCluster && args.isR) {
// In yarn-cluster mode for a R app, add primary resource to files
// that can be distributed with the job
args.files = mergeFileLists(args.files, args.primaryResource)
}
对于普通scala/java作业,standalone情况下直接调用下面类
// In legacy standalone cluster mode, use Client as a wrapper around the user
class childMainClass = "org.apache.spark.deploy.Client"
在client模式下直接提交用户应用主类运行,这里的主类如果是SPARKR_SHELL的话就是org.apache.spark.api.r.RBackend
直接提交文件执行则调用org.apache.spark.deploy.RRunner
// In client mode, launch the application main class directly
// In addition, add the main application jar and any added jars (if any) to the classpath
if (deployMode == CLIENT) {
childMainClass = args.mainClass
if (isUserJar(args.primaryResource)) {
childClasspath += args.primaryResource
} if (args.jars != null) {
childClasspath ++= args.jars.split(",")
} if (args.childArgs != null) {
childArgs ++= args.childArgs
}
}
在yarnCluster模式调度情况下,使用org.apache.spark.deploy.yarn.Client
这个类包装用户的类进行提交
// In yarn-cluster mode, use yarn.Client as a wrapper around the user class
if (isYarnCluster) {
childMainClass = "org.apache.spark.deploy.yarn.Client"
if (args.isPython) {
childArgs += ("--primary-py-file", args.primaryResource)
if (args.pyFiles != null) {
childArgs += ("--py-files", args.pyFiles)
}
childArgs += ("--class", "org.apache.spark.deploy.PythonRunner")
} else if (args.isR) {
val mainFile = new Path(args.primaryResource).getName
childArgs += ("--primary-r-file", mainFile)
childArgs += ("--class", "org.apache.spark.deploy.RRunner")
} else {
if (args.primaryResource != SPARK_INTERNAL) {
childArgs += ("--jar", args.primaryResource)
}
childArgs += ("--class", args.mainClass)
} if (args.childArgs != null) {
args.childArgs.foreach { arg => childArgs += ("--arg", arg)
}
}
}
org.apache.spark.deploy.yarn.Client
Py调用spark过程,在python/pyspark/context.py下面存在
class SparkContext(object)
其中的_jvm成员作为py4j的调用存在,其初始化
233 if not SparkContext._gateway:
234 SparkContext._gateway=gateway or launch_gateway()
235 SparkContext._jvm=SparkContext._gateway.jvm
其调用后端方法
207 # Create a temporary directory inside spark.local.dir:
208 local_dir = self._jvm.org.apache.spark.util.Utils.getLocalDir(self._jsc.sc().conf())
209 self._temp_dir = \
210 self._jvm.org.apache.spark.util.Utils.createTempDir(local_dir, "pyspark") \
211 .getAbsolutePath()
sparkR原理的更多相关文章
- 奇异值分解(SVD)原理与在降维中的应用
奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 线性判别分析LDA原理总结
在主成分分析(PCA)原理总结中,我们对降维算法PCA做了总结.这里我们就对另外一种经典的降维方法线性判别分析(Linear Discriminant Analysis, 以下简称LDA)做一个总结. ...
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
- H5单页面手势滑屏切换原理
H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...
- .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理
.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理 0x00 问题的产生 管道是.NET Core中非常关键的一个概念,很多重要的组件都以中间件的形式存在,包括权限管理.会话管理 ...
- python自动化测试(2)-自动化基本技术原理
python自动化测试(2) 自动化基本技术原理 1 概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...
- CRC、反码求和校验 原理分析
3月份开始从客户端转后台,算是幸运的进入全栈工程师的修炼阶段.这段时间一边是老项目的客户端加服务器两边的维护和交接,一边是新项目加加加班赶工,期间最长经历了连续工作三天只睡了四五个小时的煎熬,人生也算 ...
- 菜鸟学Struts2——Struts工作原理
在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...
随机推荐
- N个数字中随机取m个数子,不重复
<script> function rand_nums(min,max,count){ var arr = []; for(var i=min;i<max;i++){ arr.pus ...
- MySQL的数据类型(转)
MySQL的数据类型 1.整数 TINYINT: 8 bit 存储空间 SMALLINT: 16 bit 存储空间 MEDIUMINT: 24 bit 存储空间 INT: 32 bit 存储空间 BI ...
- java_包含抽象方法的枚举类
package ming; enum Operation { PLUS { public double eval(double x, double y) { return x + y; } }, MI ...
- 取得root权限后怎么删除程序
不知道这个算什么教程,随便一个分类吧,管理员不要扣我分啊,我也是为大家服务嘛,不对的话可以帮我处理下) 最近也学习了下,把我的X8(国行2.1版)给root了,怎么root,论坛里有很多帖子,这里就不 ...
- 【转】Singleton单例模式
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务:一个系统只能有一个窗口管理器或文件系统:一个系统只能有一个计时工具或ID(序号)生成器. ...
- C#开发-ftp操作方法整理
1.整理简化了下C#的ftp操作,方便使用 1.支持创建多级目录 2.批量删除 3.整个目录上传 4.整个目录删除 5.整个目录下载 2.调用方法展示, var ftp ...
- jQuery UI - draggable 中文API
·概述 在任何DOM元素启用拖动功能.通过单击鼠标并拖动对象在窗口内的任何地方移动. 官方示例地址:http://jqueryui.com/demos/draggable/ 所有的事件回调函数都有两个 ...
- dll不同的调用方式
LoadLibrary 一般是动态加载DLL时(你并不需要对应的头文件,和LIB) #pragma comment 一般是静态加载DLL时(对应的头文件.DLL,和LIB缺一不可,并且生产的EXE没有 ...
- [转]第一章 Windows Shell是什么 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987862】
一个操作系统外壳的不错的定义是它是一个系统提供的用户界面,它允许用户执行公共的任务,如访问文件系统,导出执行程序,改变系统设置等.MS-DOS有一个Command.COM扮演着这个角色.然而Windo ...
- 第七篇、CSS3新增属性
<!-- 1.透明度 opacity(设置不透明度):0.2: --rgba --background-color:rgba(255,0,0,0.8); 2.块阴影和圆角阴影 --box-sha ...