这次不扯蛋,直接开讲。
该问题的本质是序列化问题!!!序列化问题!!!序列化问题!!!
重要问题说三遍。
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
序列化和反序列化为的是对象经过传输(也可能是通过文件方式)后,程序还能对他进行还原成对应object。
序列化 详解 左拐 https://www.cnblogs.com/xdp-gacl/p/3777987.html
那么为什么会报上面那个问题呢?
因为你传输的对象没有序列化,或者序列化错误。java中序列化 是 java.io.Serializable;
但是 该序列化方式开销比较大,如果使用网络传输大量对象,那么可能造成带宽的大量浪费。所以spark自己搞了个序列化方式。org.apache.spark.serializer.KryoSerializer。该序列化方式好处是开销小。
spark 2.0以上版本 默认org.apache.spark.serializer.KryoSerializer序列化方式。如果你使用java 序列化那么铁定跪了。所以统一spark序列化方式 要不是这 spark成java序列化方式
conf.set("spark.serializer", "org.apache.spark.serializer.JavaSerializer")
要不对象注册成 KryoSerializer序列化方式。
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.set("spark.kryo.registrationRequired", "true")
var arrclasses: Array[Class[_]] =Array(classOf[Sub], classOf[DMPUser],
classOf[SubType], classOf[org.apache.avro.generic.GenericData.Array[_]], classOf[BasicTag]
, classOf[ExtendTag], classOf[org.apache.avro.util.Utf8], classOf[java.util.HashMap[_, _]], classOf[java.util.Map[_, _]]
, classOf[java.util.ArrayList[_]], classOf[java.util.List[_]], classOf[java.lang.CharSequence])
conf.registerKryoClasses(arrclasses)
但是有时 使用KryoSerializer注册也不是很方便。比如你用avro格式定义的嵌套格式。完了和我上面的例子一样 需要注册一大堆类。还不一定注册全。那么怎么办呢。
通用解决方式:
写代码 实现 objectToByte 和 byteToObject 方法。在有传输操作地方 将object转换成byte数组,在接收操作地方再转回来。
对于初学各种大数据格式的小朋友会遇到问题。比如 avro自动生成的类报上面错,无从下手。主要是 对avro理解错误。avro提供序列化方式,但是使用avro工具生成的类本身没有序列化!!!但是使用avro工具生成的类本身没有序列化!!!但是使用avro工具生成的类本身没有序列化!!!。avro提供了序列化类,例如DatumReader。
如果使用scala编程,可以使用case class来定义类。case class 默认实现了java 序列化方式。