java kafka消费者和avro deserialzier

velaa5lx  于 2021-06-06  发布在  Kafka
关注(0)|答案(2)|浏览(339)

我正在开发一个带有spark流的简单java。
我配置了一个kafka jdbc连接器(postgres to topic),我想用spark流消费者来阅读它。
我能够正确阅读主题:

./kafka-avro-console-consumer --bootstrap-server localhost:9092 --property schema.registry.url=http://localhost:8081 --property print.key=true --from-beginning --topic postgres-ip_audit

得到以下结果:
空{“id”:1557,“ip”:{“string”:“90.228.176.138”},“create\u ts”:{“long”:1554819937582}
当我将java应用程序与此配置一起使用时:

Map<String, Object> kafkaParams = new HashMap<>();
kafkaParams.put("bootstrap.servers", "localhost:9092");
kafkaParams.put("key.deserializer", StringDeserializer.class);
kafkaParams.put("value.deserializer", StringDeserializer.class);
kafkaParams.put("group.id", "groupStreamId");
kafkaParams.put("auto.offset.reset", "latest");
kafkaParams.put("enable.auto.commit", false);

我得到这样的结果:
�179.20.119.53�����z
有人能告诉我怎么解决我的问题吗?
我还尝试使用bytearraydeserializer并将字节[]转换为字符串,但总是得到错误的字符结果。

fslejnso

fslejnso1#

您提供了一个stringdeserializer,但是您正在发送用avro序列化的值,因此需要相应地反序列化它们。使用spark 2.4.0(和以下deps)编译 org.apache.spark:spark-avro_2.12:2.4.1 你可以通过使用 from_avro 功能:

import org.apache.spark.sql.avro._

// `from_avro` requires Avro schema in JSON string format.
val jsonFormatSchema = new String(Files.readAllBytes(Paths.get("path/to/your/schema.avsc")))

val df = spark
  .readStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
  .option("subscribe", "topic1")
  .load()
Dataset<Row> output = df
  .select(from_avro(col("value"), jsonFormatSchema).as("user"))
  .where("user.favorite_color == \"red\"")
  .show()

如果您需要使用模式注册表(就像您对kafka avro console consumer所做的那样),那么不可能开箱即用,而且需要编写大量代码。我推荐使用这个库https://github.com/absaoss/abris. 但是它只与spark 2.3.0兼容

jecbmhm3

jecbmhm32#

您可以使用 io.confluent.kafka.serializers.KafkaAvroDeserializer 以及在模式注册表中管理模式记录。
下面是一个示例代码片段

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import io.confluent.kafka.serializers.KafkaAvroDecoder;
import kafka.serializer.StringDecoder;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.streaming.Durations;
import org.apache.spark.streaming.api.java.JavaPairInputDStream;
import org.apache.spark.streaming.api.java.JavaStreamingContext;
import org.apache.spark.streaming.kafka.KafkaUtils;
import scala.Tuple2;

public class SparkStreaming {

  public static void main(String... args) {
    SparkConf conf = new SparkConf();
    conf.setMaster("local[2]");
    conf.setAppName("Spark Streaming Test Java");

    JavaSparkContext sc = new JavaSparkContext(conf);
    JavaStreamingContext ssc = new JavaStreamingContext(sc, Durations.seconds(10));

    processStream(ssc, sc);

    ssc.start();
    ssc.awaitTermination();
  }

  private static void processStream(JavaStreamingContext ssc, JavaSparkContext sc) {
    System.out.println("--> Processing stream");

    Map<String, String> props = new HashMap<>();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("schema.registry.url", "http://localhost:8081");
    props.put("group.id", "spark");
    props.put("specific.avro.reader", "true");

    props.put("value.deserializer", "io.confluent.kafka.serializers.KafkaAvroDeserializer");
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

    Set<String> topicsSet = new HashSet<>(Collections.singletonList("test"));

    JavaPairInputDStream<String, Object> stream = KafkaUtils.createDirectStream(ssc, String.class, Object.class,
      StringDecoder.class, KafkaAvroDecoder.class, props, topicsSet);

    stream.foreachRDD(rdd -> {
      rdd.foreachPartition(iterator -> {
          while (iterator.hasNext()) {
            Tuple2<String, Object> next = iterator.next();
            Model model = (Model) next._2();
            System.out.println(next._1() + " --> " + model);
          }
        }
      );
    });
  }
}

完整的示例应用程序可在此github repo中获得

相关问题