驱动程序无法从每个分区的所有执行程序接收数据

时间:2017-01-07 10:32:28

标签: apache-spark

我对spark的了解是初学者级的,我创建了一个程序,它将从目录中读取所有文件并应用一些转换并将结果保存到HDFS中。我使用的是Spark + Yarn。

IIUC,我的工作只有1个阶段和5个任务。现在,由于我的目录有22个文件,我假设将有22个分区(假设文件大小<块大小),并且这5个任务中的每一个都将在每个分区上执行。

我提供了4个执行程序,我可以看到4个执行程序正在Spark UI上运行。

问题

我希望每次执行程序完成分区上的所有任务时,驱动程序都会收到10条记录,但它并没有这样做。相反,它看起来像驱动程序只打印一个分区的输出。我做错了什么?或者我的理解错了吗?

以下是代码 -

没什么特别的;只需应用一堆转换并修改输入行并将其保存到HDFS中。

@Override
public void process() {
    // _inputDirectoryName has 22 files inside it.

    JavaRDD<String> linesRDD = _context.textFile(_inputDirectoryName);

    JavaRDD<StringBuilder> resultRDD = linesRDD
            .filter(row -> !AirlineDataUtils.isHeader(row))             
            .map(row -> AirlineDataUtils.getSelectResultsPerRow(row))
            .map(new Function<String[], StringBuilder>() {

                private static final long serialVersionUID = -3504370368751118677L;

                @Override
                public StringBuilder call(String[] arrayRow) throws Exception {
                    String delayType = null;
                    int departureDelay = AirlineDataUtils.parseMinutes(arrayRow[8], 0);
                    int arrivalDelay = AirlineDataUtils.parseMinutes(arrayRow[9], 0);

                    if(departureDelay >= _delayInMinutes && arrivalDelay >= _delayInMinutes) {
                        delayType = "B";
                    } else if(departureDelay >= _delayInMinutes){
                        delayType = "D";
                    } else if (arrivalDelay >= _delayInMinutes) {
                        delayType = "O";
                    }

                    if(delayType != null) {
                        return AirlineDataUtils.mergeStringArray(arrayRow, ",").append(delayType);
                    } else {
                        return null;
                    }
                }
            })
            .filter(row -> row != null);

    resultRDD.saveAsTextFile(_outputFileName);
    resultRDD.take(10).forEach(System.out :: println);
}

以下是我开火的命令 -

spark-submit --class com.sanjeevd.sparksimple.airlines.JobRunner 
--master yarn 
--deploy-mode client
--driver-memory=1g
--executor-memory 1g
--executor-cores 1
--num-executors 4
--driver-java-options "$DRIVER_JAVA_OPTS"
--conf spark.yarn.jars=hdfs://sanjeevd.xxx:9000/user/spark/share/lib/*.jar SparkSimple-0.0.1-SNAPSHOT.jar select-all-where

我得到的输出是

  

SLF4J:类路径包含多个SLF4J绑定。   SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/slf4j-log4j12-1.7.5.jar!/ org / slf4j /中找到绑定IMPL / StaticLoggerBinder.class]   SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/avro-tools-1.7.6-cdh5.4.7.jar中找到绑定!/组织/ SLF4J / IMPL / StaticLoggerBinder.class]   SLF4J:有关解释,请参阅http://www.slf4j.org/codes.html#multiple_bindings。   SLF4J:实际绑定的类型为[org.slf4j.impl.Log4jLoggerFactory]   14分之10/ 1987,0741,0912,SAN,SFO,447,91,79,11,23B   10/15 / 1987,0729,0903,SAN,SFO,447,94,79,-1,14O   17分之10/ 1987,0741,0918,SAN,SFO,447,97,79,11,29B   19分之10/ 1987,0749,0922,SAN,SFO,447,93,79,19,33B   23分之10/ 1987,0731,0902,SAN,SFO,447,91,79,1,13O   24分之10/ 1987,0744,0908,SAN,SFO,447,84,79,14,19B   26分之10/ 1987,0735,0904,SAN,SFO,447,89,79,5,15O   28分之10/ 1987,0741,0919,SAN,SFO,447,98,90,16,24B   29分之10/ 1987,0742,0906,SAN,SFO,447,84,90,17,11B   10月1日/ 1987,0936,1035,SFO,RNO,192,59,46,21,34B   SLF4J:类路径包含多个SLF4J绑定。   SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/slf4j-log4j12-1.7.5.jar!/ org / slf4j /中找到绑定IMPL / StaticLoggerBinder.class]   SLF4J:在[jar:file:/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/jars/avro-tools-1.7.6-cdh5.4.7.jar中找到绑定!/组织/ SLF4J / IMPL / StaticLoggerBinder.class]   SLF4J:有关解释,请参阅http://www.slf4j.org/codes.html#multiple_bindings。   SLF4J:实际绑定的类型为[org.slf4j.impl.Log4jLoggerFactory] ​​

1 个答案:

答案 0 :(得分:1)

如果您仅使用take(10)filter转换在RDD上调用map,则spark将从随机分区返回10个匹配的行。 Spark以懒惰方式执行take动作,因此它读取一个分区,如果少于10个结果,那么它会再探测4个,然后再探测20个等等,所以我假设你的代码甚至没有触及剩下的21个文件在HDFS上(你可以确保查看SparkUI)

您正在寻找的可能是foreachPartition操作 - 它为驱动程序传递可迭代分区内容的每个分区执行一个函数,因此您可以轻松打印样本行。