Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ApacheSpark:如何构造Spark应用程序的代码(特别是在使用广播时)_Java_Performance_Optimization_Apache Spark - Fatal编程技术网

Java ApacheSpark:如何构造Spark应用程序的代码(特别是在使用广播时)

Java ApacheSpark:如何构造Spark应用程序的代码(特别是在使用广播时),java,performance,optimization,apache-spark,Java,Performance,Optimization,Apache Spark,我有一个关于Java Spark应用程序中代码结构的一般性问题。我想将Spark转换的实现代码与调用RDD的代码分开,这样即使在使用包含大量代码行的大量转换时,应用程序的源代码也会保持清晰 我先给你举个简单的例子。在此场景中,flatMap转换的实现作为匿名内部类提供。这是一个简单的应用程序,它读取整数的RDD,然后将每个元素乘以一个整数数组,该数组在以下情况之前广播到所有工作节点: public static void main(String[] args) { SparkConf

我有一个关于Java Spark应用程序中代码结构的一般性问题。我想将Spark转换的实现代码与调用RDD的代码分开,这样即使在使用包含大量代码行的大量转换时,应用程序的源代码也会保持清晰

我先给你举个简单的例子。在此场景中,flatMap转换的实现作为匿名内部类提供。这是一个简单的应用程序,它读取整数的RDD,然后将每个元素乘以一个整数数组,该数组在以下情况之前广播到所有工作节点:

public static void main(String[] args) {

    SparkConf conf = new SparkConf().setMaster("local").setAppName("MyApp");
    JavaSparkContext sc = new JavaSparkContext(conf);

    JavaRDD<Integer> result = sc.parallelize(Arrays.asList(5, 8, 9));

    final Broadcast<int[]> factors = sc.broadcast(new int[] { 1, 2, 3 });

    result = result.flatMap(new FlatMapFunction<Integer, Integer>() {
        public Iterable<Integer> call(Integer t) throws Exception {
            int[] values = factors.value();
            LinkedList<Integer> result = new LinkedList<Integer>();
            for (int value : values) result.add(t * value);
            return result;
        }
    });

    System.out.println(result.collect());   // [5, 10, 15, 8, 16, 24, 9, 18, 27]

    sc.close();
}
这是使用类
SparkFunctions
的应用程序的第二个版本:

public static void main(String[] args) {

    SparkConf conf = new SparkConf().setMaster("local").setAppName("MyApp");
    JavaSparkContext sc = new JavaSparkContext(conf);

    JavaRDD<Integer> result = sc.parallelize(Arrays.asList(5, 8, 9));

    final Broadcast<int[]> factors = sc.broadcast(new int[] { 1, 2, 3 });

    // 1) Initializing
    SparkFunctions functions = new SparkFunctions();

    // 2) Pass reference of broadcast variable
    functions.setFactors(factors);

    // 3) Implementation is now in the class SparkFunctions
    result = result.flatMap(functions.myFunction);

    System.out.println(result.collect());   // [5, 10, 15, 8, 16, 24, 9, 18, 27]

    sc.close();
}
publicstaticvoidmain(字符串[]args){
SparkConf conf=new SparkConf().setMaster(“本地”).setAppName(“MyApp”);
JavaSparkContext sc=新的JavaSparkContext(conf);
javarddresult=sc.parallelize(Arrays.asList(5,8,9));
最终广播系数=sc.Broadcast(新的int[]{1,2,3});
//1)初始化
SparkFunctions functions=新的SparkFunctions();
//2)通过广播变量的引用
函数。设定因子(因子);
//3)现在在SparkFunctions类中实现
结果=result.flatMap(functions.myFunction);
System.out.println(result.collect());//[5,10,15,8,16,24,9,18,27]
sc.close();
}
应用程序的两个版本都在工作(本地和集群设置),但我想问它们是否同样有效

问题1:在我看来,Spark序列化了包含广播变量的类
SparkFunctions
,并将其发送到工作节点,以便节点可以在其任务中使用该函数。数据是否两次发送到工作节点,第一次是在使用
SparkContext
的广播上,第二次是在类
SparkFunctions
的序列化上?或者每个元素发送一次(加上1次广播)

问题2:你能为我提供一些关于如何构建源代码的建议吗

请不要提供如何阻止广播的解决方案。我有一个更复杂的实际应用程序

我发现的类似问题实际上没有帮助:


提前感谢您的帮助

这是关于问题1

提交spark作业时,作业分为阶段->任务。这些任务实际上在工作节点上执行转换和操作。驱动程序的sumbitTask()将把有关广播变量的函数和元数据序列化到所有节点

剖析广播工作原理。

驱动程序创建一个本地目录来存储要广播的数据,并启动一个可以访问该目录的HttpServer。调用广播时,数据实际上写入目录(val bdata=sc.broadcast(data))。同时,数据还通过StorageLevel memory+磁盘写入驱动程序的BlockManager。块管理器为数据分配块ID(类型为BroadcastBlockId)


只有当执行器将其接收到的任务反序列化时,才会广播真实数据,它还会以广播对象的形式获取广播变量的元数据。然后调用元数据对象(bdata变量)的readObject()方法。此方法将首先检查本地块管理器,查看是否已经存在本地副本。否则,将从驱动程序中获取数据。提取数据后,数据将存储在本地块管理器中,以供后续使用。

我想您已经回答了我的问题。从main方法提供给SparkFunctions类的广播对象只包含元数据,而不包含数据本身。那么这个解决方案应该有效地工作。非常感谢。
public static void main(String[] args) {

    SparkConf conf = new SparkConf().setMaster("local").setAppName("MyApp");
    JavaSparkContext sc = new JavaSparkContext(conf);

    JavaRDD<Integer> result = sc.parallelize(Arrays.asList(5, 8, 9));

    final Broadcast<int[]> factors = sc.broadcast(new int[] { 1, 2, 3 });

    // 1) Initializing
    SparkFunctions functions = new SparkFunctions();

    // 2) Pass reference of broadcast variable
    functions.setFactors(factors);

    // 3) Implementation is now in the class SparkFunctions
    result = result.flatMap(functions.myFunction);

    System.out.println(result.collect());   // [5, 10, 15, 8, 16, 24, 9, 18, 27]

    sc.close();
}