在阅读http://spark.apache.org/docs/0.8.0/cluster-overview.html上的一些文件后,我得到了一些我想澄清的问题。
从Spark获取此示例:
JavaSparkContext spark = new JavaSparkContext(
new SparkConf().setJars("...").setSparkHome....);
JavaRDD<String> file = spark.textFile("hdfs://...");
// step1
JavaRDD<String> words =
file.flatMap(new FlatMapFunction<String, String>() {
public Iterable<String> call(String s) {
return Arrays.asList(s.split(" "));
}
});
// step2
JavaPairRDD<String, Integer> pairs =
words.map(new PairFunction<String, String, Integer>() {
public Tuple2<String, Integer> call(String s) {
return new Tuple2<String, Integer>(s, 1);
}
});
// step3
JavaPairRDD<String, Integer> counts =
pairs.reduceByKey(new Function2<Integer, Integer>() {
public Integer call(Integer a, Integer b) {
return a + b;
}
});
counts.saveAsTextFile("hdfs://...");
因此,假设我有3个节点集群,节点1作为主节点运行,上面的驱动程序已经正确地进行了监控(比如application-test.jar)。所以现在我在主节点上运行此代码,我相信在创建SparkContext
之后,application-test.jar文件将被复制到工作节点(并且每个工作人员将为此创建一个目录)应用程序)。
所以现在我的问题:
是否将示例任务中的step1,step2和step3发送给工作人员?如果是,那么工人如何执行呢?像java -cp "application-test.jar" step1
等等?
答案 0 :(得分:91)
创建SparkContext
时,每个工作人员都会启动执行程序。这是一个单独的进程(JVM),它也会加载你的jar。执行程序连接回驱动程序。现在,驱动程序可以向您发送命令,例如您的示例中的flatMap
,map
和reduceByKey
。当驱动程序退出时,执行程序关闭。
RDD类似于大型数组,它们被分成多个分区,每个执行者都可以拥有其中的一些分区。
任务是通过序列化Function
对象从驱动程序发送到执行程序的命令。执行程序反序列化命令(这是可能的,因为它已经加载了你的jar),并在分区上执行它。
(这是一个概念性的概述。我正在浏览一些细节,但我希望它有用。)
回答您的具体问题:不,每个步骤都没有启动新流程。在构建SparkContext
时,每个工作人员都会启动一个新流程。
答案 1 :(得分:29)
为了清楚地了解如何创建和安排任务,我们必须了解执行模型在Spark中的工作原理。简而言之,spark中的应用程序分三步执行:
在你的单词计数示例中,RDD图非常简单,如下所示:
file - &gt;线 - &gt;单词 - &gt;每字数 - &gt;全球字数 - &gt;输出
基于此图表,创建了两个阶段。阶段创建规则基于管理尽可能多的窄变换的想法。在您的示例中,窄变换按字数统计。因此,你得到两个阶段
一旦计算出阶段,spark就会从阶段产生任务。第一阶段将创建ShuffleMapTasks,最后一个阶段将创建ResultTasks,因为在最后阶段,包含一个动作操作以产生结果。
要生成的任务数取决于文件的分发方式。假设您在三个不同的节点中有3个不同的文件,第一个阶段将生成3个任务:每个分区一个任务。
因此,您不应直接将步骤映射到任务。任务属于某个阶段,与分区相关。
通常,为一个阶段运行的任务数正好是最终RDD的分区数,但由于RDD可以共享(因此ShuffleMapStages
),因此它们的数量会因RDD /阶段共享而异。请参阅How DAG works under the covers in RDD?