【问题标题】:Java Kafka consumer and avro deserialzierJava Kafka 消费者和 avro 反序列化器
【发布时间】:2019-08-30 19:57:32
【问题描述】:

我正在开发一个带有火花流的简单 java。

我配置了一个 kafka jdbc 连接器(postgres 到主题),我想用一个 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_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 并将 bytes[] 转换为字符串,但我总是得到错误的字符结果。

【问题讨论】:

    标签: java apache-spark apache-kafka avro


    【解决方案1】:

    您提供了一个 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 兼容

    【讨论】:

      【解决方案2】:

      您可以使用io.confluent.kafka.serializers.KafkaAvroDeserializer 反序列化 avro 消息,并使用架构注册表来管理记录架构。

      这里是一个示例代码sn -p

      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);
                }
              }
            );
          });
        }
      }
      

      Complete sample application is available in this github repo

      【讨论】:

      • 已经尝试过,但我得到:线程“main”中的异常 org.apache.kafka.common.config.ConfigException:配置值的无效值 io.confluent.kafka.serializers.KafkaAvroDeserializer.deserializer:类io.confluent.kafka.serializers.KafkaAvroDeserializer 找不到。我正在使用融合 5.2.1
      • 这些依赖你添加了吗? &lt;dependency&gt; &lt;groupId&gt;io.confluent&lt;/groupId&gt; &lt;artifactId&gt;kafka-avro-serializer&lt;/artifactId&gt; &lt;version&gt;${confluent.version}&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;org.apache.avro&lt;/groupId&gt; &lt;artifactId&gt;avro&lt;/artifactId&gt; &lt;version&gt;${avro.version}&lt;/version&gt; &lt;/dependency&gt;
      • 我有 avro 1.8.2 和 kafka-avro-confluent 0.1.0
      • 该类是“avro-serializer”的一部分github.com/confluentinc/schema-registry/blob/master/…
      • 我找不到适用于 kafka-avro-serializer 的 maven,您能帮忙吗?
      猜你喜欢
      • 1970-01-01
      • 2017-03-06
      • 2019-08-14
      • 2018-12-08
      • 2019-04-29
      • 2016-12-09
      • 2019-05-11
      • 2019-11-18
      • 2015-08-01
      相关资源
      最近更新 更多