1.问题原因
spark处理的数据单元为RDD,当我们对RDD做诸如map,filter等操作的时候,其执行是在excutor上完成的。但是,如果我们在driver中定义了一个变量,在map等操作中使用,则这个变量就要被分发到各个excutor,因为driver和excutor运行在不同的jvm中,势必会涉及到对象的序列化与反序列化,如果这个变量没法序列化就会报异常。(如果引用的对象可以序列化,但是引用对象本身引用的其他对象无法序列化,也会报异常。)
2.解决方法
- 将不可序列化的对象定义在闭包中
在算子内初始化类
- 将所调用的方法改为函数,在高阶函数中使用
函数无状态的
- 给无法序列化的类加上Serializable接口
直接实现接口
- 注册序列化类
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") //指定序列化类为KryoSerializer
conf.registerKryoClasses(Array(classOf[net.bigdataer.spark.UnserializableClass])) //将UnserializableClass注册到kryo需要序列化的类中