KStreamBuilder无法将数据从1个主题流式传输到另一个主题

时间:2016-07-26 14:21:44

标签: apache-kafka kafka-consumer-api apache-kafka-streams

我试图使用KStreamBuilder将数据从1个主题移动到另一个主题。我尝试了以下代码,异常

angular.js:13920 Error: [$compile:tpload] Failed to load template: app/phone-list/phone-list.template.html (HTTP status: 404 Not Found)

输出

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.kstream.KStreamBuilder;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsConfig;

import java.util.Properties;

public class StreamsInTopic {

public static void main(String[] args) throws Exception {
    Properties props = new Properties();
    props.put(StreamsConfig.APPLICATION_ID_CONFIG, "streams-pipe");
    props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9094");
    props.put(StreamsConfig.KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
    props.put(StreamsConfig.VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());
    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

    KStreamBuilder builder = new KStreamBuilder();
    System.out.println("KStreamBuilder initialized!!");

    builder.stream("nil_PF1_P1").to("nil_RF1_P1_1");
    System.out.println("Streaming prepared!!");

    KafkaStreams streams = new KafkaStreams(builder, props);
    System.out.println("KafkaStreams Initialised!!");

    streams.start();
    System.out.println("Streams started!!");

    Thread.sleep(30000L);
    streams.close();
    System.out.println("Streams closed!!");
}
}

然后我尝试使用数据。

KStreamBuilder initialized!!
Streaming prepared!!
log4j:WARN No appenders could be found for logger (org.apache.kafka.streams.StreamsConfig).
log4j:WARN Please initialize the log4j system properly.
KafkaStreams Initialised!!
Streams started!!
Exception in thread "StreamThread-1" java.lang.IllegalArgumentException: Invalid timestamp -1
at org.apache.kafka.clients.producer.ProducerRecord.<init>(ProducerRecord.java:60)
at org.apache.kafka.streams.processor.internals.SinkNode.process(SinkNode.java:72)
at org.apache.kafka.streams.processor.internals.StreamTask.forward(StreamTask.java:338)
at org.apache.kafka.streams.processor.internals.ProcessorContextImpl.forward(ProcessorContextImpl.java:187)
at org.apache.kafka.streams.processor.internals.SourceNode.process(SourceNode.java:64)
at org.apache.kafka.streams.processor.internals.StreamTask.process(StreamTask.java:174)
at org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:320)
at org.apache.kafka.streams.processor.internals.StreamThread.run(StreamThread.java:218)
Streams closed!!

有什么想法吗?我需要任何附加配置吗? 我正在使用kafka 0.10.0.0集群和客户端。

使用的依赖关系。

$  bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic nil_RF1_P1_1 --from-beginning

2 个答案:

答案 0 :(得分:2)

看看你在问题中分享的内容,问题似乎是你没有在输入主题中编写(=生成)任何数据&#34; nil_PF1_P1&#34;:

  • Kafka Streams应用程序配置为从Kafka输入主题&#34; nil_PF1_P1&#34;写入数据。到Kafka输出主题&#34; nil_RF1_P1_1&#34;。
  • 控制台消费者从(应用程序的输出主题)&#34;&#34; nil_RF1_P1_1&#34;中读取任何数据。
  • 但是,您没有提及是否或如何将数据输入到输入主题&#34; nil_PF1_P1&#34;。

另外:您正在关闭代码中的Kafka Streams实例:

streams.start();
System.out.println("Streams started!!");

//Thread.sleep(1000L);
streams.close();

这不会给应用程序足够的时间来实际执行任何处理。通常,您只需在上面的streams.start()方法中调用main,并在Java应用程序中注册一个在触发时调用streams.close()的关闭挂钩。

出于测试/开发目的,您当然也可以在streams.close()内拨打main(),但是我会在开始和结束之间增加睡眠时间(例如尝试30秒) 1秒钟) - 当然,您还需要确保在该时间窗口内实际将一些数据写入应用程序的输入主题。

编辑: java.lang.IllegalArgumentException: Invalid timestamp -1错误的原因很可能是您使用非0.10生产者将数据写入输入主题。详情请见http://docs.confluent.io/current/streams/faq.html#invalid-timestamp-exception

答案 1 :(得分:1)

Kafka Stream首次发布版本为0.10,因此要求写入主题的所有记录都有关联的时间戳(键和值旁边的附加字段,在v0.10中引入)。对于Streams,此时间戳不能为负数(即使代理不检查此值并允许插入带有负时间戳的数据)。

因此,可能会发生用旧Java生成器(即0.10前生成器)编写的主题写入缺少时间戳字段的记录。您也可以使用“旧”主题,即写入0.9代理的主题,然后将代理升级到0.10 - 所有这些消息都不会设置时间戳。出于兼容性原因,KafkaConsumer(v0.10)将缺少的时间戳设置为值-1

在Kafka Streams中,在内部,输入消息的时间戳被“转发”到输出消息,因此,如果您使用没有时间戳的消息,Kafka Streams会尝试将带有时间戳-1的消息写入输出主题,从而导致以上错误。 (Kafka Streams使用0.10 Java生成器来检查时间戳是否有效,并为负时间戳值抛出上述异常)。

要避免此问题,您需要通过流配置参数timestamp.extractor更改使用的时间戳提取器(请参阅http://docs.confluent.io/3.0.0/streams/developer-guide.html#optional-configuration-parameters)。根据您的语义,您可以使用WallclockTimestampExtractor或提供自定义提取器。