【Spark】Spark运行报错Task not serializable

版权声明:本文为博主原创文章,未经博主允许不得转载。转载请附上博主博文网址,并标注作者。违者必究 https://blog.csdn.net/HuHui_/article/details/83905302

异常信息

org.apache.spark.SparkException: Task not serializable

Caused by: java.io.NotSerializableException:

出现场景

跑Spark程序的时候有可能会出现。

执行RDD行为的时候,map、filter等的方法使用了外部的变量,但是这个变量没有或者不能序列化

以前接手项目没发现这个Exception,这次自己写单元测试反而跑出来了

在我写【Spark】RDD开发手册(JavaAPI函数式编程)单元测试的时候发现的。

自推荐一下:

【Spark】RDD开发手册(JavaAPI函数式编程)
https://blog.csdn.net/HuHui_/article/details/83905308

解决方案

  • 方案1:

注意小坑:Java的 @Transient 注解是方法级别的,不是变量级别。所以不要想着@Transient放在 sparkContext头上…

/**
* 类首先要序列化
* @since hui_project 1.0.0
*/
public class TransformationRDDTest implements Serializable

/**
* sparkContext 和 SparkConf 要加上 transient
* @since hui_project 1.0.0
*/
private transient JavaSparkContext sparkContext;

private transient SparkConf sparkConf; 

/**
* 外部引用的方法加上@Transient  
* @since hui_project 1.0.0
*/
@Transient
private Iterator<Tuple2<Integer, Integer>> getSquare(Iterator<Integer> it) {}

  • 方案2:
/**
* 类首先要序列化
* @since hui_project 1.0.0
*/
public class TransformationRDDTest implements Serializable

/**
* 外部引用的方法用static
* @since hui_project 1.0.0
*/
private static Iterator<Tuple2<Integer, Integer>> getSquare(Iterator<Integer> it) {}
  • 方案3:
  sparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");

分析

这里我也是通过查资料,找到各种方法,很多我尝试后没成功。也有大部分是针对的Scala的,没有说的太清楚解决方案和针对java怎么解决。

不过其实这跟scala和java关系不大,我把搜索引擎找到的分析和资料做个小总结。

特别感谢这篇BLOG的博主:

https://blog.csdn.net/silentwolfyh/article/details/53187945

下面重点分析

在编写Spark程序中,由于在map等算子内部使用了外部定义的变量和函数,由于外部定义的变量和函数有可能不支持序列化,仍然会导致整个类序列化时出现问题,最终可能会出现Task未序列化问题。

引用了类的成员函数,会导致该类及所有成员都需要支持序列化。因此,对于使用了某类成员变量或函数的情形,首先该类需要序列化(Serializable),同时需要对某些不需要序列化的成员变量标记以避免为序列化造成影响。

编程建议

  1. 引用了类的成员函数或变量,对应的类需要做序列化处理
  2. 执行map等方法的时候,尽量不要在闭包内部直接引用成员函数或变量

猜你喜欢

转载自blog.csdn.net/HuHui_/article/details/83905302