Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Kafka streams错误:序列化异常:LongDeserializer接收的数据大小不是8_Java_Apache Kafka_Apache Kafka Streams - Fatal编程技术网

Java Kafka streams错误:序列化异常:LongDeserializer接收的数据大小不是8

Java Kafka streams错误:序列化异常:LongDeserializer接收的数据大小不是8,java,apache-kafka,apache-kafka-streams,Java,Apache Kafka,Apache Kafka Streams,我正在尝试卡夫卡流。编写一个简单的应用程序,其中我正在计算重复消息 信息: 2019-02-27-11:16:56 :: session:prod-111656 :: Msg => Hello World: 2491 2019-02-27-11:16:56 :: session:prod-111656 :: Msg => Hello World: 2492 等等 我正在尝试按会话:prod xxxx拆分此类邮件。把它当作钥匙。和session:prod xxxx+Hello Wor

我正在尝试卡夫卡流。编写一个简单的应用程序,其中我正在计算重复消息

信息:

2019-02-27-11:16:56 :: session:prod-111656 :: Msg => Hello World: 2491
2019-02-27-11:16:56 :: session:prod-111656 :: Msg => Hello World: 2492
等等

我正在尝试按
会话:prod xxxx
拆分此类邮件。把它当作钥匙。和
session:prod xxxx+Hello World:xxxx
将其用作值。然后按键分组,查看在每个会话中复制了哪些消息

代码如下:

KStream<String, String> textLines = builder.stream("RegularProducer");
KTable<String, Long> ktable = textLines.map(
    (String key, String value) -> {
        try {
            String[] parts = value.split("::");
            String sessionId = parts[1];
            String message = ((parts[2]).split("=>"))[1];
            message = sessionId+":"+message;
            return new KeyValue<String,String>(sessionId.trim().toLowerCase(), message.trim().toLowerCase());
        } catch (Exception e) {
            return new KeyValue<String,String>("Invalid-Message".trim().toLowerCase(), "Invalid Message".trim().toLowerCase());
        }
    })
    .groupBy((key,value) -> value)
    .count().filter(
            (String key, Long value) -> {
                return value > 1;
            }
    );

ktable.toStream().to("RegularProducerDuplicates", 
Produced.with(Serdes.String(), Serdes.Long()));
Topology topology = builder.build();
topology.describe();
KafkaStreams streams = new KafkaStreams(topology, props);
streams.start();

有谁能帮我这里出了什么问题吗?

您的Kafka Streams应用程序运行正常

该错误位于
kafka控制台使用者中(
kafka.tools.ConsoleConsumer
是实现脚本逻辑的类)

在反序列化过程中,它不能正确处理
null
。当它获取
null
作为消息的值或键时,它将设置默认值(表示
null
字符串的字节数组)。如果您检查源代码,您可以找到以下函数

def write(反序列化器:选项[deserializer[\u]],sourceBytes:Array[Byte]){
val nonNullBytes=选项(sourceBytes).getOrElse(“null”.getBytes(StandardCharsets.UTF_8))
val convertedBytes=deserializer.map(u.deserialize(null,nonNullBytes).toString。
getBytes(StandardCharsets.UTF_8)).getOrElse(非空字节)
output.write(转换字节)
}
如何查看当它获取空的sourceBytes(
sourceBytes==null
)进行反序列化时,它会为此设置默认值:

val nonNullBytes=Option(sourceBytes).getOrElse(“null”.getBytes(StandardCharsets.UTF_8))

在您的例子中,它是
“null”.getBytes(StandardCharsets.UTF_8)
。然后,尝试使用
org.apache.kafka.common.serialization.LongDeserializer
(您的值反序列化器)进行反序列化
LongDeserializer
从一开始就检查字节数组的大小。现在是4(表示为
null
)并引发异常

例如,如果您使用StringDeserializer,它将不会正确地对其进行反序列化,但至少不会引发异常,因为它不会检查字节数组的长度

长话短说:ConsoleConsumer的格式化程序,负责打印,为漂亮的打印设置了一些默认值,这是某些反序列化程序(LongDeserializer、IntegerDeserializer)无法处理的

关于为什么应用程序为某些键生成
null
值:

KTable:filter
KStream::filter
具有不同的语义。根据javadoc for KTable:

对于每个被删除的记录(即,不满足给定的 谓词)转发墓碑记录


对于您的
过滤器
,当
计数时,我遇到了同样的问题,发现如果我将
过滤器
移动到
之后,将不会生成空值(逻辑删除)。

用于值的反序列化程序可能不用于字符串,并且会持续很长时间。 在cli中创建使用者时,请指定它。前-

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
    --topic name \
    --from-beginning \
    --formatter kafka.tools.DefaultMessageFormatter \
    --property print.key=true \
    --property print.value=true \
    --skip-message-on-error \
    --property key.deserializer=org.apache.kafka.common.serialization.StringDeserializer \
    --property value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
这里检查最后两行,在创建消费者时,注意您的(键、值)类型 在我的例子中,这两个都是字符串,如果值是长类型的,则使用最后一行作为:
--property value.deserializer=org.apache.kafka.common.serialization.LongDeserializer

您正在对其进行反序列化,就好像该值是一个long。好像不是。你能告诉我在哪里吗?我对streams非常陌生,还不熟悉这种编程风格。(字符串键,长值)-->似乎值不是长的(正如反序列化程序所告诉的,它不是8字节长的值)。最肯定的是,这是一根弦。p、 s我对流也不太了解,但似乎是典型的kafka issueHmmm,因为在count()的前一步中,返回的值是类型t和Long。根据文件。真想知道这里出了什么问题。@Shades88,你能不能把用于阅读的整个命令(kafka控制台使用者)添加到这个问题上?不,即使我从一开始就没有,也会发生这种情况。对于没有计数=1或不重复的每条进线,此错误为thrown@Shades88,我更新了我的答案,解释了发生了什么。很好的解释。在这种情况下,我想分组,计数,然后过滤。因此,我将无法使用KStream::filter。那么我怎样才能避免墓碑记录呢?同样,通过这个过滤函数,我指定Kafka Streams,只给我KTable中那些值大于1的记录。我刚刚运行了一个标准Java消费程序,您是对的。有许多记录的值为null。那么过滤函数的作用是什么?@Shades88,当您将
KTable
转换为
KStream
时,您可以过滤掉逻辑删除代码:
KTable.toStream.filter((键,值)->value!=null)
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 \
    --topic name \
    --from-beginning \
    --formatter kafka.tools.DefaultMessageFormatter \
    --property print.key=true \
    --property print.value=true \
    --skip-message-on-error \
    --property key.deserializer=org.apache.kafka.common.serialization.StringDeserializer \
    --property value.deserializer=org.apache.kafka.common.serialization.StringDeserializer