转载自: http://bigdataer.net/?p=569

1.背景

在使用spark开发分布式数据计算作业过程中或多或少会遇到如下的错误:

Serialization stack:
object not serializable (class:class: org.apache.hadoop.hbase.io.ImmutableBytesWritable, value: 30 30 30 30 30 30 32 34 32 30 32 37 37 32 31)
field (class: scala.Tuple2, name: _1, type: class java.lang.Object) ……

或者如下的错误:

org.apache.spark.SparkException: Task not serializable at org.apache.spark.util.ClosureCleaner …

表面意思都是无法序列化导致的。spark运行过程中为什么要序列化?下面来分析一下。

2.分析

spark处理的数据单元为RDD(即弹性分布式数据集),当我们要对RDD做诸如map,filter等操作的时候是在excutor上完成的。但是如果我们在driver中定义了一个变量,在map等操作中使用,则这个变量就要被分发到各个excutor,因为driver和excutor的运行在不同的jvm中,势必会涉及到对象的序列化与反序列化。如果这个变量没法序列化就会报异常。还有一种情况就是引用的对象可以序列化,但是引用的对象本身引用的其他对象无法序列化,也会有异常

3.解决方案

(1) 举例

class UnserializableClass {
def method(x:Int):Int={
x*x
}
}

另外,有如下的spark代码块:

object SparkTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(1 to 10, 3)
val usz = new UnserializableClass()
rdd.map(x=>usz.method(x)).foreach(println(_))
}
}

那么运行的时候就会抛出异常

Exception in thread “main” org.apache.spark.SparkException: Task not serializable
at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:304)
at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:294)
at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:122)
at org.apache.spark.SparkContext.clean(SparkContext.scala:2055)
at org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala:324)
at org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala:323)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:150)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:111)
at org.apache.spark.rdd.RDD.withScope(RDD.scala:316)
at org.apache.spark.rdd.RDD.map(RDD.scala:323)
at net.bigdataer.spark.SparkTest$.main(SparkTest.scala:16)

(2) 解决方案

1. 将不可序列化的对象定义在闭包内

object SparkTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(1 to 10,3)
rdd.map(x=>new UnserializableClass().method(x)).foreach(println(_)) //在map中创建UnserializableClass对象
}
}

2.将所调用的方法改为函数,在高阶函数中使用

class UnserializableClass {
//method方法
/*def method(x:Int):Int={
x*x
}*/ //method函数
val method = (x:Int)=>x*x
}
在SparkTest中传入函数
object SparkTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(1 to 10,3)
val usz = new UnserializableClass()
rdd.map(usz.method).foreach(println(_)) //注意这里传入的是函数
}
}

3.给无法序列化的类加上java.io.Serializable接口

class UnserializableClass extends java.io.Serializable{ //加接口
def method(x:Int):Int={
x*x
}
}

4.注册序列化类

以上三个方法基于UnserializableClass可以被修改来说的,假如UnserializableClass来自于第三方,你无法修改其源码就可以使用为其注册序列化类的方法。

object SparkTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[*]").setAppName("test") conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") //指定序列化类为KryoSerializer
conf.registerKryoClasses(Array(classOf[net.bigdataer.spark.UnserializableClass])) //将UnserializableClass注册到kryo需要序列化的类中 val sc = new SparkContext(conf)
val rdd = sc.parallelize(1 to 10,3)
val usz = new UnserializableClass()
rdd.map(x=>usz.method(x)).foreach(println(_))
}
}

第一种方法比较简单实用。

spark not serializable异常分析及解决方案的更多相关文章

  1. Java ConcurrentModificationException 异常分析与解决方案

    Java ConcurrentModificationException 异常分析与解决方案http://www.2cto.com/kf/201403/286536.html java.util.Co ...

  2. 【转】Java ConcurrentModificationException 异常分析与解决方案--还不错

    原文网址:http://www.2cto.com/kf/201403/286536.html 一.单线程 1. 异常情况举例 只要抛出出现异常,可以肯定的是代码一定有错误的地方.先来看看都有哪些情况会 ...

  3. Selenium常见异常分析及解决方案

    pycharm中导入selenium报错 现象: pycharm中输入from selenium import webdriver, selenium标红 原因1: pycharm使用的虚拟环境中没有 ...

  4. hive on spark:return code 30041 Failed to create Spark client for Spark session原因分析及解决方案探寻

    最近在Hive中使用Spark引擎进行执行时(set hive.execution.engine=spark),经常遇到return code 30041的报错,为了深入探究其原因,阅读了官方issu ...

  5. Canal 同步异常分析:Could not find first log file name in binary log index file

    文章首发于[博客园-陈树义],点击跳转到原文Canal同步异常分析:Could not find first log file name in binary log index file. 公司搜索相 ...

  6. flume常见异常汇总以及解决方案

    flume常见异常汇总以及解决方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际生产环境中,我用flume将kafka的数据定期的往hdfs集群中上传数据,也遇到过一系列的坑 ...

  7. 第一篇:Spark SQL源码分析之核心流程

    /** Spark SQL源码分析系列文章*/ 自从去年Spark Submit 2013 Michael Armbrust分享了他的Catalyst,到至今1年多了,Spark SQL的贡献者从几人 ...

  8. Linux Kernel Oops异常分析

    1.PowerPC小系统内核异常分析 1.1  异常打印 Unable to handle kernel paging request for data at address 0x36fef31eFa ...

  9. MySQL 外键异常分析

    外键约束异常现象 如下测例中,没有违反引用约束的插入失败. create database `a-b`; use `a-b`; SET FOREIGN_KEY_CHECKS=0; create tab ...

随机推荐

  1. csu 1756: Prime

    1756: Prime Submit Page   Summary   Time Limit: 3 Sec     Memory Limit: 128 Mb     Submitted: 281    ...

  2. sas(Serial Attached SCSI)技术详解

    1.什么是SAS 即串行SCSI技术,是一种磁盘连接技术,它综合了并行SCSI和串行连接技术(FC,SSA,IEEE1394)的优势,以串行通讯协议为协议基础架构,采用SCSI-3扩展指令集,并兼容S ...

  3. Python 面向对象总结

    面向对象 类 class 类型 类变量 实例方法 init attack bite 类指针 - 指向父类 对象 对象指针 实例变量 self.name slef.age 组合 一个对象作为一个属性 s ...

  4. Vmware中安装的Ubuntu不能全屏问题解决

    现在有了开源的vmtoll可以下载:open-vm-tools   先安装open-vm-tools:sudo  apt-get install open-vm-tools   然后安装:(不知道具体 ...

  5. 版本管理——Git和SVN的介绍及其优缺点

    版本管理 概念:版本管理是软件配置管理的基础,它管理并保护开发者的软件资源.   好处:可以保留我们的历史版本,在代码开发到一半的时候,不至于无故丢失,还可以查看BUG的来龙去脉.   版本管理种类: ...

  6. pandas之分组计算笔记

    分组计算三部曲:拆分-->应用-->合并 分组:就是按照行或列把相同索引的部分分到一起 分组的关键词为groupby,分组后我们就可以对每组数据进行同一操作,返回的是每组数据分别计算后的结 ...

  7. gin PostForm 方法不起作用

    情景: 在httpie post 下,在 axios post下,总的来说,就是在form-data下只有c.Bind()会有用 如果一定要用c.PostForm() headers必须为x-www- ...

  8. SQLSERVER中计算某个字段中用分隔符分割的字符的个数

    比如字段sid中用'|'分割的一些字符   a|b|c|d,需要通过sql查询出字符的个数是4. 可以使用如下脚本: SELECT LEN(sid)-LEN(REPLACE(sid,'|',''))+ ...

  9. IntelliJ Idea清除Open Recent里面的项目列表

    2种方法清除IntelliJ Idea 中 Open Recent里面的项目列表 第一种方法: 如下图: Open Recent -> Manage Projects Recent Projec ...

  10. hdu 5900 区间dp

    题意:给你n对pair 里面有两个值,分别是key 和 val .你可以取相邻的两个pair 获得其中的val,前提是两个pair 的key 的 gcd 不为 1.当然你把相邻的两个取走了之后原本不相 ...