我有一个用Scala编写的Spark应用,该应用正在读写Parquet文件。 该应用程序公开一个HTTP API,当它接收请求时,通过长期存在的上下文将工作发送到Spark集群,该上下文在应用程序的生命周期中一直存在。 然后将结果返回到HTTP客户端。
当我使用本地模式并以local[*]
作为主模式时,所有这些都可以正常工作。
但是,一旦我尝试连接到Spark集群,就会遇到序列化问题。
使用Spark的默认序列化程序,我得到以下信息:
java.lang.ClassCastException: cannot assign instance of scala.collection.immutable.List$SerializationProxy to field org.apache.spark.sql.execution.FilterExec.otherPreds of type scala.collection.Seq in instance of org.apache.spark.sql.execution.FilterExec
。
如果启用Kryo序列化程序,则会得到java.lang.IllegalStateException: unread block data
。
尝试读取Parquet文件时会发生这种情况,但是我不认为这与Parquet文件本身有关,只是与要发送到Spark集群的代码的序列化有关。
从大量的互联网搜索中,我收集到这可能是由于Spark版本甚至Java版本之间的不兼容性造成的。 但是使用的版本是相同的。
该应用程序是用Scala 2.12.8编写的,并随Spark 2.4.3一起提供。 Spark集群正在运行Spark 2.4.3(使用Scala 2.12编译的版本)。 同时运行Spark集群和应用程序的机器正在使用openJDK 1.8.0_212。
根据另一个互联网搜索,问题可能出在spark.master
URL中。
因此,我将spark.master
中的spark-defaults.conf
设置为我在应用程序中用于与其连接的相同值。
但是,这并不能解决问题,我现在的想法已经用光了。
答案 0 :(得分:0)
我并不完全确定基本解释是什么,但我通过将应用程序的jar复制到Spark的jars
目录中来解决了。然后,我仍然遇到一个错误,但又是一个错误:缺少某个Cats/kernel/Eq
类的东西。因此,我将cats-kernel
的jar添加到Spark的jars
目录中。
现在一切正常。我在另一个Stack Overflow线程中读到的内容可能解释了这一点:
我认为,只要您使用引用项目的方法/类的lambda进行任何类型的映射操作,都需要将它们作为附加jar提供。 Spark确实对lambda本身进行了序列化,但没有将其依赖关系放在一起。不确定为什么错误消息根本无法提供信息。