Apache spark 从spark shell中的分布式操作调用'JValue.extract'时出错
我试图在Spark中使用json4s的案例类提取功能, ie调用Apache spark 从spark shell中的分布式操作调用'JValue.extract'时出错,apache-spark,json4s,Apache Spark,Json4s,我试图在Spark中使用json4s的案例类提取功能, ie调用jvalue.extract[MyCaseClass]。如果我将JValue对象带到主对象中并在那里进行提取,效果会很好,但是在worker中相同的调用失败: import org.json4s._ import org.json4s.jackson.JsonMethods._ import scala.util.{Try, Success, Failure} val sqx = sqlContext val data = sc
jvalue.extract[MyCaseClass]
。如果我将JValue
对象带到主对象中并在那里进行提取,效果会很好,但是在worker中相同的调用失败:
import org.json4s._
import org.json4s.jackson.JsonMethods._
import scala.util.{Try, Success, Failure}
val sqx = sqlContext
val data = sc.textFile(inpath).coalesce(2000)
case class PageView(
client: Option[String]
)
def extract(json: JValue) = {
implicit def formats = org.json4s.DefaultFormats
Try(json.extract[PageView]).toOption
}
val json = data.map(parse(_)).sample(false, 1e-6).cache()
// count initial inputs
val raw = json.count
// count successful extractions locally -- same value as above
val loc = json.toLocalIterator.flatMap(extract).size
// distributed count -- always zero
val dist = json.flatMap(extract).count // always returns zero
// this throws "org.json4s.package$MappingException: Parsed JSON values do not match with class constructor"
json.map(x => {implicit def formats = org.json4s.DefaultFormats; x.extract[PageView]}).count
由于DefaultFormats不可序列化,因此在extract
函数中本地定义了格式的隐式,并且在顶层定义它会导致将其序列化以传输到工作程序,而不是在那里构造。我认为问题仍然与DefaultFormats
的远程初始化有关,但我不确定这是什么
当我直接调用extract
方法,而不是像上一个示例中那样调用extract
函数时,它不再抱怨序列化,而是抛出一个错误,即JSON与预期结构不匹配
分配给工人时,我如何才能使提取工作正常进行
编辑
@卫斯理缪重现了这个问题,发现它是火花壳特有的。他报告说,这段代码作为一个独立的应用程序工作。正如我建议的那样,我将对象创建移动到地图中。也就是说,我将拥有函数createPageViews
,该函数将提取作为内部函数,并将createPageViews
传递给工作人员
更准确地说,我将使用mapPartitions而不是map,因此它必须在每个分区中只调用一次createPageViews
(以及它的内部函数定义部分),而不是在每个记录中调用一次。在spark shell中运行代码时,我遇到了与您相同的异常。然而,当我把你的代码变成一个真正的spark应用程序并提交给一个独立的spark集群时,我毫无例外地得到了预期的结果
下面是我在一个简单的spark应用程序中输入的代码
val data = sc.parallelize(Seq("""{"client":"Michael"}""", """{"client":"Wesley"}"""))
val json = data.map(parse(_))
val dist = json.mapPartitions { jsons =>
implicit val formats = org.json4s.DefaultFormats
jsons.map(_.extract[PageView])
}
dist.collect() foreach println
当我使用spark submit运行它时,我得到了以下结果
PageView(Some(Michael))
PageView(Some(Wesley))
我也确信它不是在“本地[*]”模式下运行的
现在我怀疑我们在spark shell中运行时出现异常的原因与spark shell中的case类PageView定义以及spark shell如何序列化/将其分发给executor有关。感谢您重现错误并确定它是特定于spark shell的。是什么让您认为问题在于case类而不是隐式格式实例?sparkshell
对构造函数做了一些奇怪的事情。有更多的细节。