转载自: 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. 初步了解Docker容器(三)

    目录 一.初步了解 1.docker run运行容器 2.docker images查看镜像 3.docker ps查看容器 4.查看其Dockerfile文件 二.Docker 知识问答 小结 一. ...

  2. 最新 腾讯java校招面试题(含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.腾讯等10家互联网公司的校招Offer,因为某些自身原因最终选择了腾讯.6.7月主要是做系统复习.项目复盘.LeetCode ...

  3. python for循环 - python基础入门(11)

    在python开发中,除了前篇文章介绍的while循环还有一个for循环也经常使用,两者使用都是大同小异,for循环的使用相对于while循环更加灵活,下面我们一起来了解下具体区别. 一.for 循环 ...

  4. 工作总结--CTO(张王岩)IO的正式使用

    4个抽象类 InputStreawm int read()  void close() OutputStream void write(int) void flush() void close() R ...

  5. java23种设计模式之八: 工厂方法模式

    定义: 定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中.这满足创建型模式中所要求的“创建与使用相分离”的特点. 我们把被创建的对象称为“产品”,把创建产品的对象称为“工 ...

  6. 多线程-Task、await/async

    Task创建无返回值 Task是.netframwork4.0重新分装的多线程类.原因以前的多线程(thread threadpool)不好用.(.net framwork也是的发展的,现在的EF,刚 ...

  7. 关于MyBatis传入String用于test判断的坑

    不要在心情糟糕的时候写代码,能坑死自己. 今天码代码的时候出现一个问题,脾气暴躁到砸桌子, 在Mybatis传入参数为String并且用 if test 判断的过程中发现 <if test=&q ...

  8. 100天搞定机器学习|Day3多元线性回归

    前情回顾 [第二天100天搞定机器学习|Day2简单线性回归分析][1],我们学习了简单线性回归分析,这个模型非常简单,很容易理解.实现方式是sklearn中的LinearRegression,我们也 ...

  9. python中集合set,字典dict和列表list的区别以及用法

    python中set代表集合,list代表列表,dict代表字典 set和dict的区别在于,dict是存储key-value,每一个key都是唯一的,set相对于dict存储的是key,且key是唯 ...

  10. Django-redis配置cache和session

    CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", &q ...