Spark相关问题的故障排除

本文深入探讨了Apache Spark的执行模型,解析了闭包内外对象的区别及其对程序性能的影响。介绍了如何避免序列化异常和单例对象导致的任务瓶颈,并讨论了异常处理的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spark的执行模型

我们遇到的大多数必须处理的问题需要先理解代码的执行环境。Spark作业是在分布式数据集上执行并行操作的驱动程序。为了解决问题需要理解代码的不同部分在哪里运行。
下面是官网的WordCount例子:

file = spark.textFile("hdfs://...")

file.flatMap(line => line.split(" "))
    .map(word => (word, 1))
    .reduceByKey(_ + _)

下图是官网的架构图:
这里写图片描述

我们知道,对于Spark开发的分布式应用程序,和写普通的scala程序基本类似。所以这时候往往会陷入一些误区:
在Spark开发的应用程序的对象里,我给他们分为2类对象:
1、闭包内的对象:即在类似map,filter,reduceByKey这样的闭包内的对象,通过会有一个函数映射。
2、闭包外的对象:反之,即闭包外的对象。
这2类对象其实是混杂在Driver和Worker里的,即并不是所有对象都会随着程序序列化到Worker里。

Spark出现NotSerializableException

如果强制将一个不支持序列化的对象方到闭包里,会报异常NotSerializableException

object MyFirstSparkJob {
  def main(args: Array[String]) {
    val ssc = new StreamingContext(args(0), "BeaconCount", Seconds(1))
    val parser = new JSONParser // <-- INSTANTIATED HERE

    val lines = ssc.textFileStream("beacons.txt")
    lines.map(line => parser.parse(line)) // <-- IN THE CLOSURE
    lines.foreach(line => println(line))

    ssc.start()
  }
}

对象JSONParser在并行操作的闭包中被引用,并被序列化到worker。但是JSONParser类不是可序列化的,会导致错误。为了解决这个问题,我们需要将JSONParser实现序列化,或者将对象移动到闭包中进行创建。

Spark任务执行特别慢并且使用的是单例线程工作

在并行的闭包操作中引用单例对象将会阻碍进程,因为这些引用将在Driver程序中发生,

object JSONParser {
  def parse(raw: String): String = ...
}

object MyFirstSparkJob {
  def main(args: Array[String]) {
    val ssc = new StreamingContext(args(0), "BeaconCount", Seconds(1))

    val lines = ssc.textFileStream("beacons.txt")
    lines.map(line => JSONParser.parse(line))
    lines.foreach(line => println(line))

    ssc.start()
  }
}

这和上一个例子的代码类似,但是这里的JSONParser对象现在是在我们的Driver程序范围内创建的单例对象。这个对象不会再worker的上下文中传递,所以Spark只会在驱动程序中执行引用该对象的代码,这对job会造成瓶颈。
为了解决这个问题,你可以把这个对象变成一个可以传递给worker进程的可序列化的类。或者你可以使用广播变量在每个worker的上下文中使这个对象可用。

Spark报java.lang.IllegalArgumentException:shuffle id XXXX registered twice

关于异常捕捉,如果在Spark Driver程序中对job的异常没有捕捉的话会导致java.lang.IllegalArgumentException: Shuffle Id Nnnn Registered Twice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值