我在Java 1.8中使用spark-sql-2.4.1v。 和kafka版本spark-sql-kafka-0-10_2.11_2.4.3和kafka-clients_0.10.0.0
StreamingQuery queryComapanyRecords =
comapanyRecords
.writeStream()
.format("kafka")
.option("kafka.bootstrap.servers",KAFKA_BROKER)
.option("topic", "in_topic")
.option("auto.create.topics.enable", "false")
.option("key.serializer","org.apache.kafka.common.serialization.StringDeserializer")
.option("value.serializer", "com.spgmi.ca.prescore.serde.MessageRecordSerDe")
.option("checkpointLocation", "/app/chkpnt/" )
.outputMode("append")
.start();
queryLinkingMessageRecords.awaitTermination();
提供错误:
Caused by: org.apache.spark.sql.AnalysisException: Required attribute 'value' not found;
at org.apache.spark.sql.kafka010.KafkaWriter$$anonfun$6.apply(KafkaWriter.scala:71)
at org.apache.spark.sql.kafka010.KafkaWriter$$anonfun$6.apply(KafkaWriter.scala:71)
at scala.Option.getOrElse(Option.scala:121)
我尝试按以下方法修复,但无法发送值,即我的情况是Java Bean。
StreamingQuery queryComapanyRecords =
comapanyRecords.selectExpr("CAST(company_id AS STRING) AS key", "to_json(struct(\"company_id\",\"fiscal_year\",\"fiscal_quarter\")) AS value")
.writeStream()
.format("kafka")
.option("kafka.bootstrap.servers",KAFKA_BROKER)
.option("topic", "in_topic")
.start();
所以在Java中无论如何,如何处理/发送该值(即Java bean作为记录)??。
答案 0 :(得分:3)
Kafka data source需要用于读取(加载)和写入(保存)数据集的特定架构。
引用official documentation(突出显示最重要的字段/列):
源代码中的每一行都具有以下架构:
...
值二进制
...
换句话说,从卡夫卡主题中读取数据时,您在value
列中有卡夫卡记录,并且还必须在value
列中将数据保存到卡夫卡主题中。
换句话说,卡夫卡中即将发生或将要发生的一切都在value
列中。 value
列是您“存储”业务记录(数据)的地方。
关于您的问题:
如何将选定的列写到Kafka主题?
您应该将选定的列“打包”在一起,以便它们可以一起成为value
列的一部分。 to_json
标准函数非常适合,因此所选的列将是JSON消息。
让我给你举个例子。
请不要忘记使用Kafka数据源启动Spark应用程序或spark-shell
。注意Scala(2.11
或2.12
)和Spark(例如2.4.4
)的版本。
spark-shell --packages org.apache.spark:spark-sql-kafka-0-10_2.11:2.4.4
让我们从创建示例数据集开始。任何多字段数据集都可以使用。
val ns = Seq((0, "zero")).toDF("id", "name")
scala> ns.show
+---+----+
| id|name|
+---+----+
| 0|zero|
+---+----+
如果我们尝试将数据集写入Kafka主题,则会由于缺少value
列而出错。那就是你最初面对的。
scala> ns.write.format("kafka").option("topic", "in_topic").save
org.apache.spark.sql.AnalysisException: Required attribute 'value' not found;
at org.apache.spark.sql.kafka010.KafkaWriter$.$anonfun$validateQuery$6(KafkaWriter.scala:71)
at scala.Option.getOrElse(Option.scala:138)
...
您必须想出一种将多个字段(列)“打包”在一起并使其作为value
列可用的方法。 struct
和to_json
标准函数可以做到这一点。
val vs = ns.withColumn("value", to_json(struct("id", "name")))
scala> vs.show(truncate = false)
+---+----+----------------------+
|id |name|value |
+---+----+----------------------+
|0 |zero|{"id":0,"name":"zero"}|
+---+----+----------------------+
保存到Kafka主题现在应该轻而易举。
vs.write.format("kafka").option("topic", "in_topic").save