[英]How to read records in JSON format from Kafka using Structured Streaming?
[英]Spark (2.2): deserialise Thrift records from Kafka using Structured Streaming
我是新來的火花。 我使用結構化流從 kafka 讀取數據。
我可以在 Scala 中使用此代碼讀取數據:
val data = spark.readStream
.format("kafka")
.option("kafka.bootstrap.servers", brokers)
.option("subscribe", topics)
.option("startingOffsets", startingOffsets)
.load()
我在值列中的數據是 Thrift 記錄。 流式 API 以二進制格式提供數據。 我看到了將數據轉換為字符串或 json 的示例,但我找不到任何有關如何將數據反序列化為 Thrift 的示例。
我怎樣才能做到這一點?
好吧,這是后續解決方案。 我不能發布我自己的代碼,但這是您可以使用的公共代碼,歸功於所有者/編碼員。
https://github.com/airbnb/airbnb-spark-thrift/blob/master/src/main/scala/com/airbnb/spark/thrift/
首先需要調用convertObject
函數將array[byte]/value轉換為Row,我們稱之為makeRow
其次,你需要通過調用convert
函數來獲取你的thrift類structType/schema,讓我們調用最終結果schema
然后你需要注冊一個像這樣的UDF val deserializer = udf((bytes: Array[Byte]) => makeRow(bytes), schema)
注意:不能在不傳遞 schema 的情況下直接使用 makeRow,否則 Spark 會報錯: Schema for type org.apache.spark.sql.Row is not supported
然后你可以這樣使用它:
val stuff = kafkaStuff.withColumn("data", deserializer(kafkaStuff("value"))) val finalStuff = stuff.select("data.*")
而且……你完成了! 希望這可以幫助。
並再次感謝這篇文章Spark UDF for StructType / Row當我以前的解決方案如此接近時,它給了我最終的想法。
我在 databricks 網站上找到了這個博客。 它展示了如何利用 Spark SQL 的 API 來使用和轉換來自 Apache Kafka 的復雜數據流。
有一節解釋了如何將 UDF 用於反序列化行:
object MyDeserializerWrapper {
val deser = new MyDeserializer
}
spark.udf.register("deserialize", (topic: String, bytes: Array[Byte]) =>
MyDeserializerWrapper.deser.deserialize(topic, bytes)
)
df.selectExpr("""deserialize("topic1", value) AS message""")
我正在使用 java,因此必須編寫以下示例 UDF,以檢查如何在 java 中調用它:
UDF1<byte[], String> mode = new UDF1<byte[], String>() {
@Override
public String call(byte[] bytes) throws Exception {
String s = new String(bytes);
return "_" + s;
}
};
現在我可以在結構化流字數統計示例中使用這個 UDF,如下所示:
Dataset<String> words = df
//converted the DataFrame to a Dataset of String using .as(Encoders.STRING())
// .selectExpr("CAST(value AS STRING)")
.select( callUDF("mode", col("value")) )
.as(Encoders.STRING())
.flatMap(
new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String x) {
return Arrays.asList(x.split(" ")).iterator();
}
}, Encoders.STRING());
我的下一步是為 thrift 反序列化編寫一個 UDF。 我會盡快發布。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.