Spark2.3(四十二):Spark Streaming和Spark Structured Streaming更新broadcast总结(二)

本次此时是在SPARK2,3 structured streaming下测试,不过这种方案,在spark2.2 structured streaming下应该也可行(请自行测试)。以下是我测试结果:

成功测试结果:

准备工作:创建maven项目,并在pom.xml导入一下依赖配置:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spark.version>2.3.0</spark.version>
        <scala.version>2.11</scala.version>
    </properties>
    <dependencies>
        <!--Spark -->
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>        
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql-kafka-0-10_${scala.version}</artifactId>
            <version>${spark.version}</version>
        </dependency>
    </dependencies>

第一步:LoadResourceManager.java是一个对broadcast类进行管理的类,

包含了以下方法:

1)unpersist()方法:对LoadResourceManager对象的broadcast属性进行清理;

2)load(SparkSession spark, LongAccumulator loadCountAccumulator)方法:实现对broadcast对象属性broadcast的初始化赋值;

3)get()方法:返回LoadResourceManager对象的broadcast属性值。

注意:该LoadResourceManager 类必须实现Serializable接口,否则会抛出不可序列化异常。

class LoadResourceManager implements Serializable {
    private static final long serialVersionUID = 7896720904164793792L;
    private volatile Broadcast<Map<String, String>> broadcast = null;

    public Broadcast<Map<String, String>> get() {
        return broadcast;
    }

    public void unpersist() {
        broadcast.unpersist(true);
//broadcast.destory(); 不能调用该方法,否则会抛出异常:Attempted to use Broadcast(x) after it was destroyed }
public void load(SparkSession spark, LongAccumulator loadCountAccumulator) { loadCountAccumulator.add(1); int val = new Random().nextInt(100); // 这里可以添加时间判断是否重新加载 Map<String, String> innerMap = new HashMap<String, String>(10); innerMap.put("1", "1," + val); innerMap.put("2", "2," + val); innerMap.put("3", "3," + val); innerMap.put("4", "4," + val); innerMap.put("5", "5," + val); innerMap.put("6", "6," + val); innerMap.put("7", "7," + val); innerMap.put("8", "8," + val); innerMap.put("9", "9," + val); innerMap.put("10", "10," + val); System.out.println("the value is :" + val); JavaSparkContext jsc = JavaSparkContext.fromSparkContext(spark.sparkContext()); broadcast = jsc.broadcast(innerMap); } }

第二步:自定义StreamingQueryListener类MyStreamingQueryListener.java

该类是spark.streams().addListener(new MyStreamingQueryListener(...))使用,在structured streaming每次trigger触发结束时打印进度信息,另外调用更新broadcast代码。其中更新broadcast的功能包含两个步骤:

1)清空旧的broadcast,也就是调用LoadResourceManager 对象的unpersist()方法;

2)给broadcast管理对象的broacast属性赋新值,也就是调用LoadResourceManager 对象的load(...)方法。

注意:这个自定义的监听类的方法是在Driver端执行,也只有在Driver端修改broadcast,才能真正修改executor中的broadcast值。具体原因,请查阅broadcast的原理。

class MyStreamingQueryListener extends StreamingQueryListener { 
    private SparkSession spark = null;
    private LoadResourceManager loadResourceManager = null;
    private LongAccumulator triggerAccumulator = null;
    private LongAccumulator loadCountAccumulator = null;

    public MyStreamingQueryListener() {
    }

    public MyStreamingQueryListener(SparkSession spark, LoadResourceManager loadResourceManager,
            LongAccumulator triggerAccumulator, LongAccumulator loadCountAccumulator) {
        this.spark = spark;
        this.loadResourceManager = loadResourceManager;
        this.triggerAccumulator = triggerAccumulator;
        this.loadCountAccumulator = loadCountAccumulator;
    }

    @Override
    public void onQueryStarted(QueryStartedEvent queryStarted) {
        System.out.println("Query started: " + queryStarted.id());
    }

    @Override
    public void onQueryTerminated(QueryTerminatedEvent queryTerminated) {
        System.out.println("Query terminated: " + queryTerminated.id());
    }

    @Override
    public void onQueryProgress(QueryProgressEvent queryProgress) {
        System.out.println("Query made progress: " + queryProgress.progress());
        // sparkSession.sql("select * from " + queryProgress.progress().name()).show();
        triggerAccumulator.add(1);
this.loadResourceManager.unpersist(); this.loadResourceManager.load(spark, loadCountAccumulator); System.out.println("Trigger accumulator value: " + triggerAccumulator.value()); System.out.println("Load count accumulator value: " + loadCountAccumulator.value()); } }

第三步:写structured streaming测试类

该测试类分为以下步骤:

1)初始化SparkSession对象spark;

2)给SparkSession对象的streams()添加监控事件:spark.streams().addListener(new MyStreamingQueryListener(...));

3)初始化broadcast管理类LoadResourceManager ,并初始化LoadResourceManager对象的broacast属性值;

4)使用Rate Source生成测试数据;

5)对测试数据进行map操作,并在MapFunction对象的call(...)方法中调用LoadResourceManager 对象的broacast属性值,使用该broacast属性值;

6)定义Sink:sourceDataset.writeStream().format("console").outputMode(OutputMode.Append()).trigger(Trigger.ProcessingTime(10, TimeUnit.SECONDS)).start();;

7)阻塞流,等待结束。

public class BroadcastTest {
    public static void main(String[] args) {
        LogManager.getLogger("org.apache.spark.sql.execution.streaming.RateSourceProvider").setLevel(Level.ERROR);
        LogManager.getLogger("org.apache.spark").setLevel(Level.ERROR);
        LogManager.getLogger("org.apache.spark.launcher.OutputRedirector").setLevel(Level.ERROR);

        // 确定是yarn方式运行。
        SparkSession spark = SparkSession.builder().master("yarn").appName("test_broadcast_app").getOrCreate();
        LongAccumulator triggerAccumulator = spark.sparkContext().longAccumulator("triggerAccumulator");
        LongAccumulator loadCountAccumulator = spark.sparkContext().longAccumulator("loadCountAccumulator");

        LoadResourceManager loadResourceManager = new LoadResourceManager();
        loadResourceManager.load(spark, loadCountAccumulator);

        spark.streams().addListener(
                new MyStreamingQueryListener(spark, loadResourceManager, triggerAccumulator, loadCountAccumulator));

        Dataset<Row> sourceDataset = spark.readStream().format("rate").option("rowsPerSecond", 100).load();

        UDF1<Long, Long> long_fomat_func = new UDF1<Long, Long>() {
            private static final long serialVersionUID = 1L;

            public Long call(final Long value) throws Exception {
                return value % 15;
            }
        };

        spark.udf().register("long_fomat_func", long_fomat_func, DataTypes.LongType);
        sourceDataset = sourceDataset.withColumn("int_id",
                functions.callUDF("long_fomat_func", functions.col("value")));
        sourceDataset.printSchema();

        StructType resulStructType = new StructType();
        resulStructType = resulStructType.add("int_id", DataTypes.StringType, false);
        resulStructType = resulStructType.add("job_result", DataTypes.StringType, true);
        ExpressionEncoder<Row> resultEncoder = RowEncoder.apply(resulStructType);

        sourceDataset = sourceDataset.map(new MapFunction<Row, Row>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Row call(Row row) throws Exception {
                int int_id_idx = row.schema().fieldIndex("int_id");
                Object int_idObject = row.get(int_id_idx);
                String int_id = int_idObject.toString();
                Map<String, String> resources = loadResourceManager.get().getValue();

                // 可能会涉及到当跨executor的情况下,依然会出现innerMap.size()返回的值为0的情况.
                if (resources.size() == 0) {
                    throw new RuntimeException("the resources size is zero");
                }
                String job_result = resources.get(int_id);

                Object[] values = new Object[2];
                values[0] = int_id;
                values[1] = job_result;

                return RowFactory.create(values);
            }
        }, resultEncoder);
        sourceDataset.printSchema();

        sourceDataset.writeStream().format("console").outputMode(OutputMode.Append())
                .trigger(Trigger.ProcessingTime(10, TimeUnit.SECONDS)).start();

        try {
            spark.streams().awaitAnyTermination();
        } catch (StreamingQueryException e) {
            e.printStackTrace();
        }
    }
}

第四步:测试。

测试脚本submit_test.sh:

#/bin/sh
jarspath=''

for file in `ls /home/dx/tommy_duan/sparkjars/*.jar`
do
  jarspath=${file},$jarspath
done
jarspath=${jarspath%?}

echo $jarspath

/home1/opt/cloudera/parcels/SPARK2-2.3.0.cloudera3-1.cdh5.13.3.p0.458809/lib/spark2/bin/spark-submit \
--master yarn \
--deploy-mode client \
--class com.dx.test.BroadcastTest \
--properties-file ./conf/spark-properties.conf \
--jars $jarspath \
--num-executors 10 \
--executor-memory 3G \
--executor-cores 1 \
--driver-memory 2G \
--driver-java-options "-XX:+TraceClassPaths" \
./test.jar $1 $2 $3 $4

执行打印结果:

。。。。。。
19/03/27 20:01:18 INFO impl.YarnClientImpl: Submitted application application_1548381669007_0775 19/03/27 20:01:47 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@3404e5c4{/metrics/json,null,AVAILABLE,@Spark} the value is :80 19/03/27 20:01:48 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@66b0e207{/SQL,null,AVAILABLE,@Spark} 19/03/27 20:01:48 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@5d601832{/SQL/json,null,AVAILABLE,@Spark} 19/03/27 20:01:48 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@3e52ed5d{/SQL/execution,null,AVAILABLE,@Spark} 19/03/27 20:01:48 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@3d40498a{/SQL/execution/json,null,AVAILABLE,@Spark} 19/03/27 20:01:48 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1de5cc88{/static/sql,null,AVAILABLE,@Spark} 19/03/27 20:01:49 INFO util.Version: Elasticsearch Hadoop v6.4.2 [54a631a014] root |-- timestamp: timestamp (nullable = true) |-- value: long (nullable = true) |-- int_id: long (nullable = true) root |-- int_id: string (nullable = false) |-- job_result: string (nullable = true) Query started: d4c76196-c874-4a09-ae2d-832c03a70ffb ------------------------------------------- Batch: 0 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ +------+----------+ Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:01:51.686Z", "batchId" : 0, "numInputRows" : 0, "processedRowsPerSecond" : 0.0, "durationMs" : { "addBatch" : 2312, "getBatch" : 38, "getOffset" : 0, "queryPlanning" : 495, "triggerExecution" : 3030, "walCommit" : 131 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : null, "endOffset" : 0, "numInputRows" : 0, "processedRowsPerSecond" : 0.0 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :26 Trigger accumulator value: 1 Load count accumulator value: 2 ------------------------------------------- Batch: 1 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 0| null| | 1| 1,26| | 2| 2,26| | 3| 3,26| | 4| 4,26| | 5| 5,26| | 6| 6,26| | 7| 7,26| | 8| 8,26| | 9| 9,26| | 10| 10,26| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,26| | 2| 2,26| | 3| 3,26| | 4| 4,26| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:02:00.001Z", "batchId" : 1, "numInputRows" : 800, "inputRowsPerSecond" : 96.21166566446182, "processedRowsPerSecond" : 14.361625736033318, "durationMs" : { "addBatch" : 55166, "getBatch" : 70, "getOffset" : 0, "queryPlanning" : 59, "triggerExecution" : 55704, "walCommit" : 402 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 0, "endOffset" : 8, "numInputRows" : 800, "inputRowsPerSecond" : 96.21166566446182, "processedRowsPerSecond" : 14.361625736033318 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :7 Trigger accumulator value: 2 Load count accumulator value: 3 ------------------------------------------- Batch: 2 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 5| 5,7| | 6| 6,7| | 7| 7,7| | 8| 8,7| | 9| 9,7| | 10| 10,7| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,7| | 2| 2,7| | 3| 3,7| | 4| 4,7| | 5| 5,7| | 6| 6,7| | 7| 7,7| | 8| 8,7| | 9| 9,7| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:02:55.822Z", "batchId" : 2, "numInputRows" : 5600, "inputRowsPerSecond" : 100.3206678490174, "processedRowsPerSecond" : 378.45509224842874, "durationMs" : { "addBatch" : 14602, "getBatch" : 24, "getOffset" : 0, "queryPlanning" : 61, "triggerExecution" : 14797, "walCommit" : 108 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 8, "endOffset" : 64, "numInputRows" : 5600, "inputRowsPerSecond" : 100.3206678490174, "processedRowsPerSecond" : 378.45509224842874 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :7 Trigger accumulator value: 3 Load count accumulator value: 4 ------------------------------------------- Batch: 3 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 10| 10,7| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,7| | 2| 2,7| | 3| 3,7| | 4| 4,7| | 5| 5,7| | 6| 6,7| | 7| 7,7| | 8| 8,7| | 9| 9,7| | 10| 10,7| | 11| null| | 12| null| | 13| null| | 14| null| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:03:10.698Z", "batchId" : 3, "numInputRows" : 1500, "inputRowsPerSecond" : 100.83355740790536, "processedRowsPerSecond" : 437.4453193350831, "durationMs" : { "addBatch" : 3253, "getBatch" : 18, "getOffset" : 0, "queryPlanning" : 42, "triggerExecution" : 3429, "walCommit" : 113 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 64, "endOffset" : 79, "numInputRows" : 1500, "inputRowsPerSecond" : 100.83355740790536, "processedRowsPerSecond" : 437.4453193350831 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :21 Trigger accumulator value: 4 Load count accumulator value: 5 ------------------------------------------- Batch: 4 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 10| 10,21| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,21| | 2| 2,21| | 3| 3,21| | 4| 4,21| | 5| 5,21| | 6| 6,21| | 7| 7,21| | 8| 8,21| | 9| 9,21| | 10| 10,21| | 11| null| | 12| null| | 13| null| | 14| null| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:03:20.000Z", "batchId" : 4, "numInputRows" : 900, "inputRowsPerSecond" : 96.7533863685229, "processedRowsPerSecond" : 664.2066420664207, "durationMs" : { "addBatch" : 599, "getBatch" : 23, "getOffset" : 0, "queryPlanning" : 36, "triggerExecution" : 1355, "walCommit" : 692 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 79, "endOffset" : 88, "numInputRows" : 900, "inputRowsPerSecond" : 96.7533863685229, "processedRowsPerSecond" : 664.2066420664207 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :76 Trigger accumulator value: 5 Load count accumulator value: 6 ------------------------------------------- Batch: 5 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 10| 10,76| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,76| | 2| 2,76| | 3| 3,76| | 4| 4,76| | 5| 5,76| | 6| 6,76| | 7| 7,76| | 8| 8,76| | 9| 9,76| | 10| 10,76| | 11| null| | 12| null| | 13| null| | 14| null| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:03:30.000Z", "batchId" : 5, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1189.0606420927468, "durationMs" : { "addBatch" : 613, "getBatch" : 21, "getOffset" : 0, "queryPlanning" : 40, "triggerExecution" : 841, "walCommit" : 164 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 88, "endOffset" : 98, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1189.0606420927468 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :1 Trigger accumulator value: 6 Load count accumulator value: 7 ------------------------------------------- Batch: 6 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 5| 5,1| | 6| 6,1| | 7| 7,1| | 8| 8,1| | 9| 9,1| | 10| 10,1| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,1| | 2| 2,1| | 3| 3,1| | 4| 4,1| | 5| 5,1| | 6| 6,1| | 7| 7,1| | 8| 8,1| | 9| 9,1| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:03:40.000Z", "batchId" : 6, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1116.0714285714284, "durationMs" : { "addBatch" : 522, "getBatch" : 18, "getOffset" : 0, "queryPlanning" : 27, "triggerExecution" : 896, "walCommit" : 325 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 98, "endOffset" : 108, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1116.0714285714284 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :5 Trigger accumulator value: 7 Load count accumulator value: 8 ------------------------------------------- Batch: 7 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 0| null| | 1| 1,5| | 2| 2,5| | 3| 3,5| | 4| 4,5| | 5| 5,5| | 6| 6,5| | 7| 7,5| | 8| 8,5| | 9| 9,5| | 10| 10,5| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,5| | 2| 2,5| | 3| 3,5| | 4| 4,5| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:03:50.000Z", "batchId" : 7, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1605.1364365971108, "durationMs" : { "addBatch" : 454, "getBatch" : 23, "getOffset" : 0, "queryPlanning" : 41, "triggerExecution" : 623, "walCommit" : 102 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 108, "endOffset" : 118, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1605.1364365971108 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :49 Trigger accumulator value: 8 Load count accumulator value: 9 ------------------------------------------- Batch: 8 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 10| 10,49| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,49| | 2| 2,49| | 3| 3,49| | 4| 4,49| | 5| 5,49| | 6| 6,49| | 7| 7,49| | 8| 8,49| | 9| 9,49| | 10| 10,49| | 11| null| | 12| null| | 13| null| | 14| null| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:04:00.000Z", "batchId" : 8, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1436.7816091954023, "durationMs" : { "addBatch" : 543, "getBatch" : 23, "getOffset" : 0, "queryPlanning" : 34, "triggerExecution" : 696, "walCommit" : 93 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 118, "endOffset" : 128, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1436.7816091954023 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :62 Trigger accumulator value: 9 Load count accumulator value: 10 ------------------------------------------- Batch: 9 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 5| 5,62| | 6| 6,62| | 7| 7,62| | 8| 8,62| | 9| 9,62| | 10| 10,62| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,62| | 2| 2,62| | 3| 3,62| | 4| 4,62| | 5| 5,62| | 6| 6,62| | 7| 7,62| | 8| 8,62| | 9| 9,62| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:04:10.001Z", "batchId" : 9, "numInputRows" : 1000, "inputRowsPerSecond" : 99.99000099990002, "processedRowsPerSecond" : 1519.756838905775, "durationMs" : { "addBatch" : 459, "getBatch" : 21, "getOffset" : 0, "queryPlanning" : 45, "triggerExecution" : 658, "walCommit" : 130 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 128, "endOffset" : 138, "numInputRows" : 1000, "inputRowsPerSecond" : 99.99000099990002, "processedRowsPerSecond" : 1519.756838905775 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :58 Trigger accumulator value: 10 Load count accumulator value: 11 ------------------------------------------- Batch: 10 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 0| null| | 1| 1,58| | 2| 2,58| | 3| 3,58| | 4| 4,58| | 5| 5,58| | 6| 6,58| | 7| 7,58| | 8| 8,58| | 9| 9,58| | 10| 10,58| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,58| | 2| 2,58| | 3| 3,58| | 4| 4,58| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:04:20.000Z", "batchId" : 10, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0100010001, "processedRowsPerSecond" : 1577.2870662460568, "durationMs" : { "addBatch" : 481, "getBatch" : 21, "getOffset" : 0, "queryPlanning" : 32, "triggerExecution" : 633, "walCommit" : 98 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 138, "endOffset" : 148, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0100010001, "processedRowsPerSecond" : 1577.2870662460568 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :42 Trigger accumulator value: 11 Load count accumulator value: 12 ------------------------------------------- Batch: 11 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 10| 10,42| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,42| | 2| 2,42| | 3| 3,42| | 4| 4,42| | 5| 5,42| | 6| 6,42| | 7| 7,42| | 8| 8,42| | 9| 9,42| | 10| 10,42| | 11| null| | 12| null| | 13| null| | 14| null| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:04:30.000Z", "batchId" : 11, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1694.9152542372883, "durationMs" : { "addBatch" : 415, "getBatch" : 18, "getOffset" : 0, "queryPlanning" : 38, "triggerExecution" : 590, "walCommit" : 118 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 148, "endOffset" : 158, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1694.9152542372883 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :29 Trigger accumulator value: 12 Load count accumulator value: 13 ------------------------------------------- Batch: 12 ------------------------------------------- +------+----------+ |int_id|job_result| +------+----------+ | 5| 5,29| | 6| 6,29| | 7| 7,29| | 8| 8,29| | 9| 9,29| | 10| 10,29| | 11| null| | 12| null| | 13| null| | 14| null| | 0| null| | 1| 1,29| | 2| 2,29| | 3| 3,29| | 4| 4,29| | 5| 5,29| | 6| 6,29| | 7| 7,29| | 8| 8,29| | 9| 9,29| +------+----------+ only showing top 20 rows Query made progress: { "id" : "d4c76196-c874-4a09-ae2d-832c03a70ffb", "runId" : "0317a974-930f-47ae-99d8-3fa582383a65", "name" : null, "timestamp" : "2019-03-27T12:04:40.000Z", "batchId" : 12, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1406.4697609001407, "durationMs" : { "addBatch" : 479, "getBatch" : 25, "getOffset" : 0, "queryPlanning" : 34, "triggerExecution" : 711, "walCommit" : 171 }, "stateOperators" : [ ], "sources" : [ { "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]", "startOffset" : 158, "endOffset" : 168, "numInputRows" : 1000, "inputRowsPerSecond" : 100.0, "processedRowsPerSecond" : 1406.4697609001407 } ], "sink" : { "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@3b5afcc" } } the value is :11 Trigger accumulator value: 13 Load count accumulator value: 14

失败测试结果:

所有类如下:

package com.dx.test;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.MapFunction;
import org.apache.spark.broadcast.Broadcast;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.functions;
import org.apache.spark.sql.api.java.UDF1;
import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder;
import org.apache.spark.sql.catalyst.encoders.RowEncoder;
import org.apache.spark.sql.streaming.OutputMode;
import org.apache.spark.sql.streaming.StreamingQueryException;
import org.apache.spark.sql.streaming.StreamingQueryListener;
import org.apache.spark.sql.streaming.Trigger;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructType;
import org.apache.spark.util.LongAccumulator;

public class BroadcastTest2 {
    public static void main(String[] args) {
        LogManager.getLogger("org.apache.spark.sql.execution.streaming.RateSourceProvider").setLevel(Level.ERROR);
        LogManager.getLogger("org.apache.spark").setLevel(Level.ERROR);
        LogManager.getLogger("org.apache.spark.launcher.OutputRedirector").setLevel(Level.ERROR);

        // 确定是yarn方式运行。
        SparkSession spark = SparkSession.builder().master("yarn").appName("test_broadcast_app").getOrCreate();
        LongAccumulator triggerAccumulator = spark.sparkContext().longAccumulator("triggerAccumulator");
        LongAccumulator loadCountAccumulator = spark.sparkContext().longAccumulator("loadCountAccumulator");
        
        LoadResourceManager.load(spark, loadCountAccumulator);
        
        spark.streams().addListener(
                new MyStreamingQueryListener(spark, triggerAccumulator, loadCountAccumulator));

        Dataset<Row> sourceDataset = spark.readStream().format("rate").option("rowsPerSecond", 100).load();

        UDF1<Long, Long> long_fomat_func = new UDF1<Long, Long>() {
            private static final long serialVersionUID = 1L;

            public Long call(final Long value) throws Exception {
                return value % 15;
            }
        };

        spark.udf().register("long_fomat_func", long_fomat_func, DataTypes.LongType);
        sourceDataset = sourceDataset
                .withColumn("int_id", functions.callUDF("long_fomat_func", functions.col("value")));
        sourceDataset.printSchema();

        StructType resulStructType = new StructType();
        resulStructType = resulStructType.add("int_id", DataTypes.StringType, false);
        resulStructType = resulStructType.add("job_result", DataTypes.StringType, true);
        ExpressionEncoder<Row> resultEncoder = RowEncoder.apply(resulStructType);

        sourceDataset = sourceDataset.map(new MapFunction<Row, Row>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Row call(Row row) throws Exception {
                int int_id_idx = row.schema().fieldIndex("int_id");
                Object int_idObject = row.get(int_id_idx);
                String int_id = int_idObject.toString();
                Map<String, String> resources = LoadResourceManager.get().getValue();

                // 可能会涉及到当跨executor的情况下,依然会出现innerMap.size()返回的值为0的情况.
                if (resources.size() == 0) {
                    throw new RuntimeException("the resources size is zero");
                }
                String job_result = resources.get(int_id);

                Object[] values = new Object[2];
                values[0] = int_id;
                values[1] = job_result;

                return RowFactory.create(values);
            }
        }, resultEncoder);
        sourceDataset.printSchema();

        sourceDataset.writeStream().format("console").outputMode(OutputMode.Append())
                .trigger(Trigger.ProcessingTime(10, TimeUnit.SECONDS)).start();

        try {
            spark.streams().awaitAnyTermination();
        } catch (StreamingQueryException e) {
            e.printStackTrace();
        }
    }
}

class LoadResourceManager implements Serializable{
    private static final long serialVersionUID = 7896720904164793792L;
    private static volatile Broadcast<Map<String, String>> broadcast = null;

    public static Broadcast<Map<String, String>> get() {
        return broadcast;
    }

    public static void unpersist() {
        broadcast.unpersist(true);
// broadcast.destory();不能调用该方法,否则会抛出:
Attempted to use Broadcast(x) after it was destroyed
    }

    public static void load(SparkSession spark, LongAccumulator loadCountAccumulator) {
        loadCountAccumulator.add(1);
        int val = new Random().nextInt(100);

        // 这里可以添加时间判断是否重新加载
        Map<String, String> innerMap = new HashMap<String, String>(10);
        innerMap.put("1", "1," + val);
        innerMap.put("2", "2," + val);
        innerMap.put("3", "3," + val);
        innerMap.put("4", "4," + val);
        innerMap.put("5", "5," + val);
        innerMap.put("6", "6," + val);
        innerMap.put("7", "7," + val);
        innerMap.put("8", "8," + val);
        innerMap.put("9", "9," + val);
        innerMap.put("10", "10," + val);

        System.out.println("the value is :" + val);

        JavaSparkContext jsc = JavaSparkContext.fromSparkContext(spark.sparkContext());
        broadcast = jsc.broadcast(innerMap);
    }
}

class MyStreamingQueryListener extends StreamingQueryListener {
    private SparkSession spark = null;
    private LongAccumulator triggerAccumulator = null;
    private LongAccumulator loadCountAccumulator = null;

    public MyStreamingQueryListener() {
    }

    public MyStreamingQueryListener(SparkSession spark, 
            LongAccumulator triggerAccumulator, LongAccumulator loadCountAccumulator) {
        this.spark = spark;
        this.triggerAccumulator = triggerAccumulator;
        this.loadCountAccumulator = loadCountAccumulator;
    }

    @Override
    public void onQueryStarted(QueryStartedEvent queryStarted) {
        System.out.println("Query started: " + queryStarted.id());
    }

    @Override
    public void onQueryTerminated(QueryTerminatedEvent queryTerminated) {
        System.out.println("Query terminated: " + queryTerminated.id());
    }

    @Override
    public void onQueryProgress(QueryProgressEvent queryProgress) {
        System.out.println("Query made progress: " + queryProgress.progress());
        // sparkSession.sql("select * from " +
        // queryProgress.progress().name()).show();
        triggerAccumulator.add(1);
        
        LoadResourceManager.unpersist();
        LoadResourceManager.load(spark, loadCountAccumulator);

        System.out.println("Trigger    accumulator value: " + triggerAccumulator.value());
        System.out.println("Load count accumulator value: " + loadCountAccumulator.value());
    }
}

测试打印如下:

[Opened /usr/java/jdk1.8.0_152/jre/lib/charsets.jar]
19/03/27 20:25:41 INFO impl.YarnClientImpl: Submitted application application_1548381669007_0777
19/03/27 20:26:19 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@42d9e8d2{/metrics/json,null,AVAILABLE,@Spark}
the value is :1
19/03/27 20:26:38 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@7308c820{/SQL,null,AVAILABLE,@Spark}
19/03/27 20:26:38 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@640c216b{/SQL/json,null,AVAILABLE,@Spark}
19/03/27 20:26:38 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@28e94c2{/SQL/execution,null,AVAILABLE,@Spark}
19/03/27 20:26:38 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@482a58c7{/SQL/execution/json,null,AVAILABLE,@Spark}
19/03/27 20:26:38 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@2d4fb0d8{/static/sql,null,AVAILABLE,@Spark}
19/03/27 20:26:39 INFO util.Version: Elasticsearch Hadoop v6.4.2 [54a631a014]
root
 |-- timestamp: timestamp (nullable = true)
 |-- value: long (nullable = true)
 |-- int_id: long (nullable = true)

root
 |-- int_id: string (nullable = false)
 |-- job_result: string (nullable = true)

Query started: 53290edb-bfca-4de3-9686-719ffece7fc0
-------------------------------------------
Batch: 0
-------------------------------------------
+------+----------+
|int_id|job_result|
+------+----------+
+------+----------+

Query made progress: {
  "id" : "53290edb-bfca-4de3-9686-719ffece7fc0",
  "runId" : "cf449470-f377-4270-b5ea-25230c49add2",
  "name" : null,
  "timestamp" : "2019-03-27T12:26:41.980Z",
  "batchId" : 0,
  "numInputRows" : 0,
  "processedRowsPerSecond" : 0.0,
  "durationMs" : {
    "addBatch" : 2383,
    "getBatch" : 38,
    "getOffset" : 0,
    "queryPlanning" : 554,
    "triggerExecution" : 3170,
    "walCommit" : 140
  },
  "stateOperators" : [ ],
  "sources" : [ {
    "description" : "RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]",
    "startOffset" : null,
    "endOffset" : 0,
    "numInputRows" : 0,
    "processedRowsPerSecond" : 0.0
  } ],
  "sink" : {
    "description" : "org.apache.spark.sql.execution.streaming.ConsoleSinkProvider@511c2d85"
  }
}
the value is :43
Trigger    accumulator value: 1
Load count accumulator value: 2
19/03/27 20:27:00 ERROR scheduler.TaskSetManager: Task 0 in stage 0.0 failed 4 times; aborting job
19/03/27 20:27:01 ERROR v2.WriteToDataSourceV2Exec: Data source writer org.apache.spark.sql.execution.streaming.sources.MicroBatchWriter@e074fee is aborting.
19/03/27 20:27:01 ERROR v2.WriteToDataSourceV2Exec: Data source writer org.apache.spark.sql.execution.streaming.sources.MicroBatchWriter@e074fee aborted.
19/03/27 20:27:01 ERROR streaming.MicroBatchExecution: Query [id = 53290edb-bfca-4de3-9686-719ffece7fc0, runId = cf449470-f377-4270-b5ea-25230c49add2] terminated with error
org.apache.spark.SparkException: Writing job aborted.
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec.doExecute(WriteToDataSourceV2.scala:112)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:131)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:127)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:155)
        at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
        at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:152)
        at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:127)
        at org.apache.spark.sql.execution.SparkPlan.getByteArrayRdd(SparkPlan.scala:247)
        at org.apache.spark.sql.execution.SparkPlan.executeCollect(SparkPlan.scala:294)
        at org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$collectFromPlan(Dataset.scala:3273)
        at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2722)
        at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2722)
        at org.apache.spark.sql.Dataset$$anonfun$52.apply(Dataset.scala:3254)
        at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:77)
        at org.apache.spark.sql.Dataset.withAction(Dataset.scala:3253)
        at org.apache.spark.sql.Dataset.collect(Dataset.scala:2722)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch$3$$anonfun$apply$16.apply(MicroBatchExecution.scala:478)
        at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:77)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch$3.apply(MicroBatchExecution.scala:473)
        at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:271)
        at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:58)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution.org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch(MicroBatchExecution.scala:472)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply$mcV$sp(MicroBatchExecution.scala:133)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:271)
        at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:58)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1.apply$mcZ$sp(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.ProcessingTimeExecutor.execute(TriggerExecutor.scala:56)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution.runActivatedStream(MicroBatchExecution.scala:117)
        at org.apache.spark.sql.execution.streaming.StreamExecution.org$apache$spark$sql$execution$streaming$StreamExecution$$runStream(StreamExecution.scala:279)
        at org.apache.spark.sql.execution.streaming.StreamExecution$$anon$1.run(StreamExecution.scala:189)
Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 4 times, most recent failure: Lost task 0.3 in stage 0.0 (TID 12, vm10.60.0.8.com.cn, executor 6): java.lang.NullPointerException
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:74)
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:1)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.mapelements_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.deserializetoobject_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
        at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
        at scala.collection.Iterator$class.foreach(Iterator.scala:893)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.foreach(WholeStageCodegenExec.scala:612)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:133)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:132)
        at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1415)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$.run(WriteToDataSourceV2.scala:138)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:79)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:78)
        at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
        at org.apache.spark.scheduler.Task.run(Task.scala:109)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Driver stacktrace:
        at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$failJobAndIndependentStages(DAGScheduler.scala:1609)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1597)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1596)
        at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
        at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
        at org.apache.spark.scheduler.DAGScheduler.abortStage(DAGScheduler.scala:1596)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:831)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:831)
        at scala.Option.foreach(Option.scala:257)
        at org.apache.spark.scheduler.DAGScheduler.handleTaskSetFailed(DAGScheduler.scala:831)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1830)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1779)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1768)
        at org.apache.spark.util.EventLoop$$anon$1.run(EventLoop.scala:48)
        at org.apache.spark.scheduler.DAGScheduler.runJob(DAGScheduler.scala:642)
        at org.apache.spark.SparkContext.runJob(SparkContext.scala:2034)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec.doExecute(WriteToDataSourceV2.scala:82)
        ... 31 more
Caused by: java.lang.NullPointerException
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:74)
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:1)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.mapelements_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.deserializetoobject_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
        at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
        at scala.collection.Iterator$class.foreach(Iterator.scala:893)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.foreach(WholeStageCodegenExec.scala:612)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:133)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:132)
        at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1415)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$.run(WriteToDataSourceV2.scala:138)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:79)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:78)
        at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
        at org.apache.spark.scheduler.Task.run(Task.scala:109)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
org.apache.spark.sql.streaming.StreamingQueryException: Writing job aborted.
=== Streaming Query ===
Identifier: [id = 53290edb-bfca-4de3-9686-719ffece7fc0, runId = cf449470-f377-4270-b5ea-25230c49add2]
Current Committed Offsets: {RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]: 0}
Current Available Offsets: {RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64]: 8}

Current State: ACTIVE
Thread State: RUNNABLE

Logical Plan:
SerializeFromObject [staticinvoke(class org.apache.spark.unsafe.types.UTF8String, StringType, fromString, validateexternaltype(getexternalrowfield(assertnotnull(input[0, org.apache.spark.sql.Row, true]), 0, int_id), StringType), true, false) AS int_id#14, if (assertnotnull(input[0, org.apache.spark.sql.Row, true]).isNullAt) null else staticinvoke(class org.apache.spark.unsafe.types.UTF8String, StringType, fromString, validateexternaltype(getexternalrowfield(assertnotnull(input[0, org.apache.spark.sql.Row, true]), 1, job_result), StringType), true, false) AS job_result#15]
+- MapElements com.dx.test.BroadcastTest$2@3a907688, interface org.apache.spark.sql.Row, [StructField(timestamp,TimestampType,true), StructField(value,LongType,true), StructField(int_id,LongType,true)], obj#13: org.apache.spark.sql.Row
   +- DeserializeToObject createexternalrow(staticinvoke(class org.apache.spark.sql.catalyst.util.DateTimeUtils$, ObjectType(class java.sql.Timestamp), toJavaTimestamp, timestamp#2, true, false), value#3L, int_id#6L, StructField(timestamp,TimestampType,true), StructField(value,LongType,true), StructField(int_id,LongType,true)), obj#12: org.apache.spark.sql.Row
      +- Project [timestamp#2, value#3L, UDF:long_fomat_func(value#3L) AS int_id#6L]
         +- StreamingExecutionRelation RateSource[rowsPerSecond=100, rampUpTimeSeconds=0, numPartitions=64], [timestamp#2, value#3L]

        at org.apache.spark.sql.execution.streaming.StreamExecution.org$apache$spark$sql$execution$streaming$StreamExecution$$runStream(StreamExecution.scala:295)
        at org.apache.spark.sql.execution.streaming.StreamExecution$$anon$1.run(StreamExecution.scala:189)
Caused by: org.apache.spark.SparkException: Writing job aborted.
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec.doExecute(WriteToDataSourceV2.scala:112)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:131)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:127)
        at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:155)
        at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
        at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:152)
        at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:127)
        at org.apache.spark.sql.execution.SparkPlan.getByteArrayRdd(SparkPlan.scala:247)
        at org.apache.spark.sql.execution.SparkPlan.executeCollect(SparkPlan.scala:294)
        at org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$collectFromPlan(Dataset.scala:3273)
        at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2722)
        at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2722)
        at org.apache.spark.sql.Dataset$$anonfun$52.apply(Dataset.scala:3254)
        at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:77)
        at org.apache.spark.sql.Dataset.withAction(Dataset.scala:3253)
        at org.apache.spark.sql.Dataset.collect(Dataset.scala:2722)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch$3$$anonfun$apply$16.apply(MicroBatchExecution.scala:478)
        at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:77)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch$3.apply(MicroBatchExecution.scala:473)
        at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:271)
        at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:58)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution.org$apache$spark$sql$execution$streaming$MicroBatchExecution$$runBatch(MicroBatchExecution.scala:472)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply$mcV$sp(MicroBatchExecution.scala:133)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1$$anonfun$apply$mcZ$sp$1.apply(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:271)
        at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:58)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution$$anonfun$runActivatedStream$1.apply$mcZ$sp(MicroBatchExecution.scala:121)
        at org.apache.spark.sql.execution.streaming.ProcessingTimeExecutor.execute(TriggerExecutor.scala:56)
        at org.apache.spark.sql.execution.streaming.MicroBatchExecution.runActivatedStream(MicroBatchExecution.scala:117)
        at org.apache.spark.sql.execution.streaming.StreamExecution.org$apache$spark$sql$execution$streaming$StreamExecution$$runStream(StreamExecution.scala:279)
        ... 1 more
Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 4 times, most recent failure: Lost task 0.3 in stage 0.0 (TID 12, vm10.60.0.8.com.cn, executor 6): java.lang.NullPointerException
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:74)
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:1)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.mapelements_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.deserializetoobject_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
        at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
        at scala.collection.Iterator$class.foreach(Iterator.scala:893)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.foreach(WholeStageCodegenExec.scala:612)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:133)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:132)
        at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1415)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$.run(WriteToDataSourceV2.scala:138)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:79)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:78)
        at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
        at org.apache.spark.scheduler.Task.run(Task.scala:109)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Driver stacktrace:
        at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$failJobAndIndependentStages(DAGScheduler.scala:1609)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1597)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1596)
        at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
        at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
        at org.apache.spark.scheduler.DAGScheduler.abortStage(DAGScheduler.scala:1596)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:831)
        at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:831)
        at scala.Option.foreach(Option.scala:257)
        at org.apache.spark.scheduler.DAGScheduler.handleTaskSetFailed(DAGScheduler.scala:831)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1830)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1779)
        at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1768)
        at org.apache.spark.util.EventLoop$$anon$1.run(EventLoop.scala:48)
        at org.apache.spark.scheduler.DAGScheduler.runJob(DAGScheduler.scala:642)
        at org.apache.spark.SparkContext.runJob(SparkContext.scala:2034)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec.doExecute(WriteToDataSourceV2.scala:82)
        ... 31 more
Caused by: java.lang.NullPointerException
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:74)
        at com.dx.test.BroadcastTest$2.call(BroadcastTest.java:1)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.mapelements_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.deserializetoobject_doConsume_0$(Unknown Source)
        at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
        at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
        at scala.collection.Iterator$class.foreach(Iterator.scala:893)
        at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.foreach(WholeStageCodegenExec.scala:612)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:133)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$$anonfun$run$3.apply(WriteToDataSourceV2.scala:132)
        at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1415)
        at org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask$.run(WriteToDataSourceV2.scala:138)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:79)
        at org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec$$anonfun$2.apply(WriteToDataSourceV2.scala:78)
        at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
        at org.apache.spark.scheduler.Task.run(Task.scala:109)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Query terminated: 53290edb-bfca-4de3-9686-719ffece7fc0
19/03/27 20:27:01 INFO server.AbstractConnector: Stopped Spark@af78c87{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
bash-4.1$ 

两个测试主要不同之处对比:

 

 关于这两个类测试结果不同,希望读者可以发表自己的看法:为什么使用静态方法就测试失败呢?

 

posted @ 2019-03-27 21:23  cctext  阅读(3402)  评论(0编辑  收藏  举报