我有一个自引用的protobuf模式:
message A {
uint64 timestamp = 1;
repeated A fields = 2;
}
我正在使用scalaPB
生成对应的Scala类,然后尝试按照以下步骤解码从Kafka流中消耗的消息:
def main(args : Array[String]) {
val spark = SparkSession.builder.
master("local")
.appName("spark session example")
.getOrCreate()
import spark.implicits._
val ds1 = spark.readStream.format("kafka").
option("kafka.bootstrap.servers","localhost:9092").
option("subscribe","student").load()
val ds2 = ds1.map(row=> row.getAs[Array[Byte]]("value")).map(Student.parseFrom(_))
val query = ds2.writeStream
.outputMode("append")
.format("console")
.start()
query.awaitTermination()
}
This is a related question here on StackOverflow。
但是,Spark结构化流在此行抛出循环引用错误。
val ds2 = ds1.map(row=> row.getAs[Array[Byte]]("value")).map(Student.parseFrom(_))
我理解这是因为递归引用只能在驱动程序(基本上是RDD
或Dataset
级别)上在Spark中处理。有没有人找到解决此问题的方法,例如通过UDF启用递归调用?
答案 0 :(得分:0)
事实证明,这是由于制作火花架构的方式受到限制所致。为了处理大量数据,代码与部分数据一起分布在所有从属节点上,结果通过主节点进行协调。现在,由于在工作程序节点上没有任何东西可以跟踪堆栈,因此不允许在工作程序上进行递归,而只能在驱动程序级别上进行递归。
简而言之,对于当前的spark版本,无法进行这种递归解析。最好的选择是移至具有类似库并轻松解析递归protobuf文件的Java。