Scala 使用单个开发/测试机器并发地进行Spark进程分区

Scala 使用单个开发/测试机器并发地进行Spark进程分区,scala,apache-spark,Scala,Apache Spark,我天真地在本地模式下测试并发性,使用以下spark上下文 SparkSession .builder .appName("local-mode-spark") .master("local[*]") .config("spark.executor.instances", 4) .config("spark.executor.cores", 2) .config("spark.network.timeout", "100000

我天真地在本地模式下测试并发性,使用以下spark上下文

SparkSession
      .builder
      .appName("local-mode-spark")
      .master("local[*]")
      .config("spark.executor.instances", 4)
      .config("spark.executor.cores", 2)
      .config("spark.network.timeout", "10000001") // to avoid shutdown during debug, avoid otherwise
      .config("spark.executor.heartbeatInterval", "10000000") // to avoid shutdown during debug, avoid otherwise
      .getOrCreate()
mapPartitions
API调用,如下所示:

import spark.implicits._ 

val inputDF : DataFrame = spark.read.parquet(inputFile)

val resultDF : DataFrame =
    inputDF.as[T].mapPartitions(sparkIterator => new MyIterator)).toDF
从表面上看,这确实在我的代码中发现了一个并发错误,它包含在
MyIterator
中(不是Spark代码中的错误)。但是,我希望我的应用程序能够在生产过程中以及测试过程中处理所有可用的机器资源,从而提高发现额外并发错误的机会

到目前为止,我的情况显然不是这样:在整个
inputDF
的繁重处理过程中,我的机器的CPU利用率非常低,而有大量的空闲RAM,JVM Xmx没有真正的限制

您建议如何使用本地计算机测试并发性?目的是测试在生产中,Spark不会在Spark从
MyIterator
中应用的代码中遇到线程安全或其他并发问题

或者它甚至可以在spark本地模式下并行处理输入数据帧的单独分区?我能让spark在一台机器上的同一数据帧上同时工作吗,最好是在本地模式下

  • 最大平行度
  • 您已经在本地模式下使用
    .master(“local[*])
    运行spark

    local[*]使用的线程数与Java虚拟机可用的处理器数相同(它使用Runtime.getRuntime.availableProcessors()来知道线程数)

  • 所有执行器/线程可用的最大内存
  • 我发现您没有明确设置驱动程序内存。默认情况下,驱动器内存为
    512M
    。如果您的本地计算机的空闲空间大于此值,请显式设置此值。您可以通过以下两种方式之一实现:

  • 在属性文件中设置它(默认值为spark defaults.conf)

  • 或者在运行时提供配置设置

    $ ./bin/spark-shell --driver-memory 5g
    
  • 请注意,这无法通过在应用程序中设置来实现,因为到那时已经太晚了,进程已经开始使用一些内存

  • 工作性质
  • 检查数据帧中的分区数。这将从本质上决定您可以使用的最大并行度

    inputDF.rdd.partitions.size 
    
    如果输出为1,则表示您的数据帧只有1个分区,因此在该数据帧上执行操作时不会获得并发性。在这种情况下,您可能需要调整一些配置来创建更多的分区,以便可以同时运行任务。

    是! 在本地模式下实现并行是完全可能的。 检查本地计算机中可用的内存和cpu量,并在提交spark作业时向
    驱动程序内存
    驱动程序内核
    配置提供值

    增加
    执行器内存
    执行器内核
    在该模式下不会产生任何影响

    应用程序运行后,打开该作业的SPARK UI。现在,您可以转到
    EXECUTORS
    选项卡,实际检查spark作业正在使用的资源量

    您可以使用
    作业
    阶段
    选项卡监视生成的各种任务以及作业同时运行的任务数

    为了处理比可用资源大得多的数据,请确保使用
    重新分区
    将数据分成更小的分区。这将使您的工作成功完成

    如果作业具有聚合或联接,请增加默认的随机分区。另外,请确保本地文件系统上有足够的空间,因为spark会创建中间洗牌文件并将其写入磁盘


    希望这有帮助

    运行本地模式无法模拟生产环境,原因如下

  • 在本地模式下运行代码时,有许多代码会被忽略,而本地模式通常与任何其他集群管理器一起运行。在各种各样的问题中,我能想到的事情很少
    A.无法从处理洗牌的方式中检测错误(洗牌数据在本地模式下以完全不同的方式处理)。
    B我们将无法检测到与序列化相关的问题,因为驱动程序和任务本身都可以使用所有代码,因此我们不会导致任何序列化问题。
    c无推测性任务(尤其是写操作)
    d网络相关问题,所有任务都在同一JVM中执行。您将无法检测到诸如驱动程序/执行器之间的通信、与codegen相关的问题等问题
  • 本地模式下的并发性
    a所能达到的最大并发数将等于本地计算机中的内核数。(
    BSpark UI中显示的作业、阶段和任务指标不准确,因为它会导致在驱动程序也在运行的JVM中运行的开销。
    c:至于CPU/内存利用率,这取决于正在执行的操作。操作是否占用CPU/内存
  • 何时使用本地模式
    a测试仅在驱动程序上运行的代码
    B将在执行器上执行的代码的基本健全性测试
    c单元测试

  • tl;dr在本地模式下发生的并发错误甚至可能不会出现在其他群集资源管理器中,因为本地模式的Spark代码中有很多特殊处理(有很多代码在代码中检查
    isLocal
    ,控制权完全转移到不同的代码流)

    我对本地模式的偏好是,我想这是唯一一种主设备可以使用spark的模式,而不依赖spark的任何安装,只依赖spark作为库依赖。请指定
    inputDF.rdd.partitions.size