繁体   English   中英

Kafka protobuf 的 Spark 结构化流

[英]Spark structured streaming of Kafka protobuf

我正在尝试创建一个使用 ProtoBuf 编码的 Kafka 消息的 Spark Streaming。

这是我最近几天尝试的

    import spark.implicits._
    def parseLine (str: Array[Byte]): ProtoSchema = ProtoSchema.parseFrom(str)   
    val storageLoc: String = "/tmp/avl/output"
    val checkpointLoc: String = "/tmp/avl/checkpoint"
    val dfStreamReader: DataFrame = spark
      .readStream
      .format("kafka")
      .option("kafka.bootstrap.servers", brokers)
      .option("failOnDataLoss", value = false)
      .option("subscribe", topics)
      .load()

    val dfStreamReaderValues: Dataset[Array[Byte]] = dfStreamReader.map(row => row.getAs[Array[Byte]]("value"))

    val rddProtoSchema: Dataset[ProtoSchema] = dfStreamReaderValues.map(str => parseLine(str))

    val dfRaw: DataFrame = spark.sqlContext.protoToDataFrame(rddProtoSchema.rdd)

    val streamWriterAirline: StreamingQuery = dfRaw.writeStream
      .format("parquet")
      .option("path", storageLoc)
      .option("checkpointLocation", checkpointLoc)
      .outputMode(Append)
      .trigger(ProcessingTime("2 seconds"))
      .start()
    spark.streams.awaitAnyTermination(20000)

使用 scalapb,我设法解码二进制 proto 文件并转换为 dataframe。 但是对于流式传输,我在解析行的编译时得到了这个异常:

    val rddProtoSchema: Dataset[ProtoSchema] = dfStreamReaderValues.map(str => parseLine(str))
    >>>>>
    scala.ScalaReflectionException: <none> is not a term

谁能给点提示?

更新:sparksql-scalapb 现在能够为协议缓冲区派生编码器,并且不再需要以前使用 UDT 生成器的方法。 说明可在此处获得


旧答案(现在不相关) :使用数据集时,Spark 会尝试为消息中的每个字段查找 SQL 类型。 Spark 不知道如何处理 ScalaPB 枚举(它们被表示为由 case 对象扩展的密封特征),因此它给出了这个错误。 解决方法是注册枚举和用户定义的类型。 这可以按如下方式完成:

  1. 添加 sparksql-scalapb-gen 到你的project/plugins.sbt /plugins.sbt (不是你的主build.sbt ):
libraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb-gen" % "0.8.1"

检查上面的版本是否与您正在使用的sparksql-scalapb版本匹配。

  1. 将此生成器添加到PB.targets中的build.sbt中:
PB.targets in Compile := Seq(
  scalapb.gen() -> (sourceManaged in Compile).value,
  scalapb.UdtGenerator -> (sourceManaged in Compile).value
)
  1. 重新生成源(可能需要sbt clean然后sbt compile

  2. 在你的主 function 中调用生成的注册 function。 这将是mypackage.MyFileUdt.register()

请参阅: https://scalapb.github.io/sparksql.html#datasets-and-none-is-not-a-term

示例项目: https://github.com/thesamet/sparksql-scalapb-test

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM