Spark:使用Spark Scala阅读来自卡夫卡的Avro消息
我在Spark:使用Spark Scala阅读来自卡夫卡的Avro消息,scala,apache-spark,avro,spark-structured-streaming,confluent-schema-registry,Scala,Apache Spark,Avro,Spark Structured Streaming,Confluent Schema Registry,我在spark 2.4.3中尝试下面的代码来读取来自卡夫卡的Avro消息 在kafka上发布数据时,模式存储在融合模式注册表中。 我一直在尝试一些已经在这里(/)讨论过的解决方案,但无法使其起作用。 或者我找不到合适的方法来实现这一点,尤其是当模式存储在某个模式注册表中时 这是我正在尝试的当前代码,至少我能够得到一些结果 但所有记录都显示为null值。事实上,这个话题已经有了数据。 有人能帮我一下吗 import io.confluent.kafka.schemaregistry.client.
spark 2.4.3
中尝试下面的代码来读取来自卡夫卡的Avro消息
在kafka上发布数据时,模式存储在融合模式注册表中。
我一直在尝试一些已经在这里(/)讨论过的解决方案,但无法使其起作用。
或者我找不到合适的方法来实现这一点,尤其是当模式存储在某个模式注册表中时
这是我正在尝试的当前代码,至少我能够得到一些结果
但所有记录都显示为null
值。事实上,这个话题已经有了数据。
有人能帮我一下吗
import io.confluent.kafka.schemaregistry.client.{CachedSchemaRegistryClient, SchemaRegistryClient}
import io.confluent.kafka.serializers.AbstractKafkaAvroDeserializer
import org.apache.avro.Schema
import org.apache.avro.generic.GenericRecord
import org.apache.spark.sql.avro.SchemaConverters
object ScalaSparkAvroConsumer {
private val topic = "customer.v1"
private val kafkaUrl = "localhost:9092"
private val schemaRegistryUrl = "http://127.0.0.1:8081"
private val schemaRegistryClient = new CachedSchemaRegistryClient(schemaRegistryUrl, 128)
private val kafkaAvroDeserializer = new AvroDeserializer(schemaRegistryClient)
private val avroSchema = schemaRegistryClient.getLatestSchemaMetadata(topic + "-value").getSchema
private var sparkSchema = SchemaConverters.toSqlType(new Schema.Parser().parse(avroSchema))
def main(args: Array[String]): Unit = {
val spark = getSparkSession()
spark.sparkContext.setLogLevel("ERROR")
spark.udf.register("deserialize", (bytes: Array[Byte]) =>
DeserializerWrapper.deserializer.deserialize(bytes)
)
val df = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", kafkaUrl)
.option("subscribe", topic)
.option("startingOffsets", "earliest")
.load()
val valueDataFrame = df.selectExpr("""deserialize(value) AS message""")
import org.apache.spark.sql.functions._
val formattedDataFrame = valueDataFrame.select(
from_json(col("message"), sparkSchema.dataType).alias("parsed_value"))
.select("parsed_value.*")
formattedDataFrame
.writeStream
.format("console")
.option("truncate", false)
.start()
.awaitTermination()
}
object DeserializerWrapper {
val deserializer = kafkaAvroDeserializer
}
class AvroDeserializer extends AbstractKafkaAvroDeserializer {
def this(client: SchemaRegistryClient) {
this()
this.schemaRegistry = client
}
override def deserialize(bytes: Array[Byte]): String = {
val genericRecord = super.deserialize(bytes).asInstanceOf[GenericRecord]
genericRecord.toString
}
}
}
获得如下输出:
-------------------------------------------
Batch: 0
-------------------------------------------
+------+-------+
|header|control|
+------+-------+
|null |null |
|null |null |
|null |null |
|null |null |
+------+-------+
only showing top 20 rows
Avro序列化、卡夫卡模式服务器和Spark Streaming与from_confluence_Avro()的集成将使您的生活更加轻松。你可以在这里找到它:
将Avro序列化、卡夫卡模式服务器和Spark Streaming与from_confluence_Avro()相结合,将使您的生活更加轻松。你可以在这里找到它:
可能重复的我已经尝试过我在描述中提到的那些,但无法使其工作。你能给我一些建议吗?我在那里写下了答案,可以证明它对我有效。如果得到null,则可能是生成的架构与记录内容不一致。那里的答案没有使用.a安装[GenericRecord]
,例如,您可以检查值数据框
中的内容吗?您可以执行valueDataFrame.writeStream.format(“控制台”)
?为了便于调试,请使用read
(Spark SQL)而不是readStream
(结构化流媒体),直到它给出正确的值。是的,我使用了read
,它给出了实际的消息<代码>{“header”:{“Id”:“123”},“control”:{“subject”:“EOD”}}
可能的重复项我已经尝试了我在说明中所述的那些,但无法使其工作。你能给我一些建议吗?我在那里写下了答案,可以证明它对我有效。如果得到null,则可能是生成的架构与记录内容不一致。那里的答案没有使用.a安装[GenericRecord]
,例如,您可以检查值数据框
中的内容吗?您可以执行valueDataFrame.writeStream.format(“控制台”)
?为了便于调试,请使用read
(Spark SQL)而不是readStream
(结构化流媒体),直到它给出正确的值。是的,我使用了read
,它给出了实际的消息<代码>{“header”:{“Id”:“123”},“control”:{“subject”:“EOD”}}