[英]Reading Avro messages from Kafka with Spark 2.0.2 (structured streaming)
[英]Scala: Error reading Kafka Avro messages from spark structured streaming
我一直在嘗試使用 Scala 2.11 從火花結構化流 (2.4.4) 讀取 Kafka 的 avro 序列化消息。 為此,我使用了 spark-avro(依賴關系如下)。 我使用 confluent-kafka 庫從 python 生成 kafka 消息。 Spark 流能夠使用帶有模式的消息,但它不能正確讀取字段的值。 我准備了一個簡單的例子來說明問題,代碼在這里可用: https : //github.com/anigmo97/SimpleExamples/tree/master/Spark_streaming_kafka_avro_scala
我在python中創建記錄,記錄的架構是:
{
"type": "record",
"namespace": "example",
"name": "RawRecord",
"fields": [
{"name": "int_field","type": "int"},
{"name": "string_field","type": "string"}
]
}
它們是這樣生成的:
from time import sleep
from confluent_kafka.avro import AvroProducer, load, loads
def generate_records():
avro_producer_settings = {
'bootstrap.servers': "localhost:19092",
'group.id': 'groupid',
'schema.registry.url': "http://127.0.0.1:8081"
}
producer = AvroProducer(avro_producer_settings)
key_schema = loads('"string"')
value_schema = load("schema.avsc")
i = 1
while True:
row = {"int_field": int(i), "string_field": str(i)}
producer.produce(topic="avro_topic", key="key-{}".format(i),
value=row, key_schema=key_schema, value_schema=value_schema)
print(row)
sleep(1)
i+=1
Spark 結構化流的消耗(在 Scala 中)是這樣完成的:
import org.apache.spark.sql.{ Dataset, Row}
import org.apache.spark.sql.streaming.{ OutputMode, StreamingQuery}
import org.apache.spark.sql.avro._
...
try {
log.info("----- reading schema")
val jsonFormatSchema = new String(Files.readAllBytes(
Paths.get("./src/main/resources/schema.avsc")))
val ds:Dataset[Row] = sparkSession
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", kafkaServers)
.option("subscribe", topic)
.load()
val output:Dataset[Row] = ds
.select(from_avro(ds.col("value"), jsonFormatSchema) as "record")
.select("record.*")
output.printSchema()
var query: StreamingQuery = output.writeStream.format("console")
.option("truncate", "false").outputMode(OutputMode.Append()).start();
query.awaitTermination();
} catch {
case e: Exception => log.error("onApplicationEvent error: ", e)
//case _: Throwable => log.error("onApplicationEvent error:")
}
...
在 spark 中打印模式,雖然 avro 模式不允許,但字段可以為空很奇怪。 Spark顯示了這一點:
root
|-- int_field: integer (nullable = true)
|-- string_field: string (nullable = true)
我已經在 python 中與另一個消費者檢查了消息,消息很好,但獨立於消息內容 spark 顯示了這一點。
+---------+------------+
|int_field|string_field|
+---------+------------+
|0 | |
+---------+------------+
使用的主要依賴項是:
<properties>
<spark.version>2.4.4</spark.version>
<scala.version>2.11</scala.version>
</properties>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-avro_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql-kafka-0-10_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
有誰知道為什么會發生這種情況?
提前致謝。 重現錯誤的代碼在這里:
https://github.com/anigmo97/SimpleExamples/tree/master/Spark_streaming_kafka_avro_scala
問題是我在 python 中使用 confluent_kafka 庫,我正在使用 spark-avro 庫讀取 spark 結構化流中的 avro 消息。
Confluent_kafka 庫使用 confluent 的 avro 格式,並使用標准的 avro 格式觸發 avro 讀取。
不同之處在於,為了使用模式注冊表,confluent avro 在消息前面加上四個字節,指示應該使用哪個模式。
來源: https : //www.confluent.io/blog/kafka-connect-tutorial-transfer-avro-schemas-across-schema-registry-clusters/
為了能夠使用融合 avro 並從 spark 結構化流中讀取它,我替換了 Abris 的 spark-avro 庫(abris 允許將 avro 和融合 avro 與 spark 集成)。 https://github.com/AbsaOSS/ABRiS
問題是我在 python 中使用 confluent_kafka 庫,我正在使用 spark-avro 庫讀取 spark 結構化流中的 avro 消息。
Confluent_kafka 庫使用 confluent 的 avro 格式,並使用標准的 avro 格式觸發 avro 讀取。
不同之處在於,為了使用模式注冊表,confluent avro 在消息前面加上四個字節,指示應該使用哪個模式。
來源: https : //www.confluent.io/blog/kafka-connect-tutorial-transfer-avro-schemas-across-schema-registry-clusters/
為了能夠使用融合 avro 並從 spark 結構化流中讀取它,我替換了 Abris 的 spark-avro 庫(abris 允許將 avro 和融合 avro 與 spark 集成)。 https://github.com/AbsaOSS/ABRiS
我的依賴項更改如下:
<properties>
<spark.version>2.4.4</spark.version>
<scala.version>2.11</scala.version>
</properties>
<!-- SPARK- AVRO -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-avro_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<!-- SPARK -AVRO AND CONFLUENT-AVRO -->
<dependency>
<groupId>za.co.absa</groupId>
<artifactId>abris_2.11</artifactId>
<version>3.1.1</version>
</dependency>
在這里你可以看到一個簡單的例子,它獲取消息並將其值反序列化為 avro 和 confluent avro。
var input: Dataset[Row] = sparkSession.readStream
//.format("org.apache.spark.sql.kafka010.KafkaSourceProvider")
.format("kafka")
.option("kafka.bootstrap.servers", kafkaServers)
.option("subscribe", topicConsumer)
.option("failOnDataLoss", "false")
// .option("startingOffsets", "latest")
// .option("startingOffsets", "earliest")
.load();
// READ WITH spark-avro library (standard avro)
val jsonFormatSchema = new String(Files.readAllBytes(Paths.get("./src/main/resources/schema.avsc")))
var inputAvroDeserialized: Dataset[Row] = input
.select(from_avro(functions.col("value"), jsonFormatSchema) as "record")
.select("record.*")
//READ WITH Abris library (confuent avro)
val schemaRegistryConfig = Map(
SchemaManager.PARAM_SCHEMA_REGISTRY_URL -> "http://localhost:8081",
SchemaManager.PARAM_SCHEMA_REGISTRY_TOPIC -> topicConsumer,
SchemaManager.PARAM_VALUE_SCHEMA_NAMING_STRATEGY -> SchemaManager.SchemaStorageNamingStrategies.TOPIC_NAME, // choose a subject name strategy
SchemaManager.PARAM_VALUE_SCHEMA_ID -> "latest" // set to "latest" if you want the latest schema version to used
)
var inputConfluentAvroDeserialized: Dataset[Row] = inputConfluentAvroSerialized
.select(from_confluent_avro(functions.col("value"), schemaRegistryConfig) as "record")
.select("record.*")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.