Spark streaming:com.esotericsoftware.kryo.KryoException:java.lang.IllegalArgumentException:Class未注册:scala.Tuple2 $ mcJZ $ sp

时间:2016-12-30 05:54:02

标签: scala serialization apache-spark spark-streaming kryo

我正在尝试在火花流中使用Kryo Serializer。我在Spark tuning docs读到了 -

  

最后,如果你没有注册你的自定义类,Kryo仍然会   工作,但它必须存储每个对象的完整类名,   这很浪费。

所以我想尝试注册所有课程。我的案例类是 -

trait Message extends java.io.Serializable

object MutableTypes {
  type Childs = scala.collection.mutable.Map[Int, (Long, Boolean)]
  type Parents = scala.collection.mutable.Map[Int, Childs]
}

case class IncomingRecord(id_1: String, id_raw: String, parents_to_add: MutableTypes.Parents, parents_to_delete: MutableTypes.Parents) extends Message

我正在注册这样的课程 -

sparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
  .set("spark.kryo.registrationRequired","true")
sparkConf.registerKryoClasses(Array(classOf[Tuple2[Long,Boolean]],classOf[IncomingRecord]))

我遇到了这个例外:

  

com.esotericsoftware.kryo.KryoException:   java.lang.IllegalArgumentException:未注册类:   scala.Tuple2 $ mcJZ $ sp注意:要注册此类,请使用:   kryo.register(scala.Tuple2 $ mcJZ $ sp.class);序列化跟踪:   parents_to_add(com.test.IncomingRecord)at   com.esotericsoftware.kryo.serializers.FieldSerializer $ ObjectField.write(FieldSerializer.java:585)   在   com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)   在com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:568)
  在   org.apache.spark.serializer.KryoSerializationStream.writeObject(KryoSerializer.scala:194)   在   org.apache.spark.serializer.SerializationStream.writeValue(Serializer.scala:147)   在   org.apache.spark.storage.DiskBlockObjectWriter.write(DiskBlockObjectWriter.scala:185)   在   org.apache.spark.util.collection.WritablePartitionedPairCollection $$匿名$ 1.writeNext(WritablePartitionedPairCollection.scala:56)   在   org.apache.spark.util.collection.ExternalSorter.writePartitionedFile(ExternalSorter.scala:659)   在   org.apache.spark.shuffle.sort.SortShuffleWriter.write(SortShuffleWriter.scala:72)   在   org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:73)   在   org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:41)   在org.apache.spark.scheduler.Task.run(Task.scala:89)at   org.apache.spark.executor.Executor $ TaskRunner.run(Executor.scala:214)   在   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)   在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:617)   在java.lang.Thread.run(Thread.java:745)

我如何注册课程?怎么解决这个?

更新

我知道转向注册false会删除异常,但由于额外的开销,这不会增加那么多的性能。我想知道如何注册我的班级。

2 个答案:

答案 0 :(得分:0)

  

最后,如果你没有注册你的自定义类,Kryo仍然会   工作,但它必须存储每个对象的完整类名,   这很浪费。   仅当使用spark.kryo.registrationRequired的默认值时才会出现这种情况“(这是假的)

以下内容应解决异常问题(或避免为此参数设置任何值并使用默认值false)

.set("spark.kryo.registrationRequired","false")

可以在此处找到更多信息:http://spark.apache.org/docs/latest/configuration.html

spark.kryo.registrationRequired false(默认值)是否要求注册Kryo。 如果设置为'true',如果未注册的类被序列化,Kryo将抛出异常。如果设置为false(默认值),Kryo将编写未注册的类名以及每个对象。编写类名会导致显着的性能开销,因此启用此选项可以严格执行用户未从注册中省略的类。

一些要点 - 如何注册kryo序列化:

答案 1 :(得分:0)

我在另一个stackoverflow答案中提供了一种方法,以获取需要快速注册的所有类名。

请参阅:https://stackoverflow.com/a/55644422/5981256