如何从spark设置和获取静态变量?

时间:2015-04-16 20:28:24

标签: java apache-spark spark-streaming

我有一个课程:

public class Test {
    private static String name;

    public static String getName() {
        return name;
    }

    public static void setName(String name) {
        Test.name = name;
    }

    public static void print() {
        System.out.println(name);
    }

}

在我的Spark驱动程序中,我设置了这样的名称并调用print()命令:

public final class TestDriver{

    public static void main(String[] args) throws Exception {
        SparkConf sparkConf = new SparkConf().setAppName("TestApp");
        // ...
        // ...
        Test.setName("TestName")
        Test.print();
        // ...
    }
}

但是,我得到NullPointerException。如何将值传递给全局变量并使用它?

4 个答案:

答案 0 :(得分:22)

好的,基本上有两种方法可以将master知道的值传递给执行者:

  1. 将值放入要序列化的闭包中以执行任务。这是最常见的,非常简单/优雅。示例和文档 here
  2. 使用数据创建广播变量。这适用于大尺寸的不可变数据,因此您希望保证它只发送一次。如果反复使用相同的数据也很好。示例和文档 here
  3. 在任何一种情况下都不需要使用静态变量。但是,如果您想在执行程序VM上提供静态值,则需要执行以下操作之一:

    1. 如果值已修复或配置在执行程序节点上可用(生活在jar内等),那么您可以使用惰性val,只保证初始化一次。
    2. 您可以使用上述2个选项之一的代码调用mapPartitions(),然后将值存储在静态变量/对象上。 mapPartitions保证每个分区只运行一次(比每行一次好多了),并且适合这种事情(初始化数据库连接等)。
    3. 希望这有帮助!

      P.S:至于你的异常:我只是没有在代码示例中看到它,我敢打赌它正在其他地方发生。


      编辑以获得额外的说明:懒惰的解决方案只是Scala,没有涉及Spark ......

      object MyStaticObject
      {
        lazy val MyStaticValue = {
           // Call a database, read a file included in the Jar, do expensive initialization computation, etc
           4
        }
      } 
      

      由于每个Executor都对应一个JVM,因此一旦加载了类,MyStaticObject将被初始化。 lazy关键字保证MyStaticValue变量仅在第一次实际请求时初始化,并保持其值。

答案 1 :(得分:6)

您的驱动程序进程中的类副本不是执行程序中的副本。它们不在同一个ClassLoader中,甚至不在同一个JVM中,甚至不在同一台机器上。在驱动程序上设置静态变量对其他副本没有任何作用,因此您可以远程找到它。

答案 2 :(得分:1)

我想添加另一种方法,只有当您有一些变量在运行时作为参数传递时,这种方法才有意义。

火花配置-> --conf "spark.executor.extraJavaOptions=-DcutomField=${value}" 和 当您需要转换中的数据时,可以致电System.getProperty("cutomField");

您可以找到更多详细信息here

注意:当我们有大量变量时,上面讨论的没有意义 。在这种情况下,我希望使用@Daniel Langdon的方法。

答案 3 :(得分:0)

我想在DanielL的答案中再加一点

当使用static关键字声明变量时,JVM将在类加载期间加载它,因此,如果您创建一个jar并设置Java / scala类中静态字段的初始值存储在jar中,则工作人员可以直接使用它。但是,如果您在驱动程序中更改了静态字段的值,则工作人员只能看到分配给Jar的初始值,而更改后的值将不会反映出来,因此您需要再次复制新的jar或需要手动将类复制到所有执行程序中