春季云流融合KStream Avro消费

时间:2019-11-25 11:47:40

标签: spring-boot apache-kafka apache-kafka-streams spring-cloud-stream confluent-schema-registry

我正在尝试使用Spring Boot 2.0将来自kafka主题的融合avro消息作为Kstream来使用。

我可以将消息作为MessageChannel使用,但不能作为KStream使用。

@Input(ORGANIZATION)
KStream<String, Organization> organizationMessageChannel();


@StreamListener
    public void processOrganization(@Input(KstreamBinding.ORGANIZATION)KStream<String, Organization> organization) {
        log.info("Organization Received:" + organization);
 }

例外:

  

线程异常   “ pcs-7bb7b444-044d-41bb-945d-450c902337ff-StreamThread-3”   org.apache.kafka.streams.errors.StreamsException:流线程   [pcs-7bb7b444-044d-41bb-945d-450c902337ff-StreamThread-3]失败   重新平衡。在   org.apache.kafka.streams.processor.internals.StreamThread.pollRequests(StreamThread.java:860)     在   org.apache.kafka.streams.processor.internals.StreamThread.runOnce(StreamThread.java:808)     在   org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:774)     在   org.apache.kafka.streams.processor.internals.StreamThread.run(StreamThread.java:744)   引起原因:org.apache.kafka.streams.errors.StreamsException:失败   配置值Serde类   io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde位于   org.apache.kafka.streams.StreamsConfig.defaultValueSerde(StreamsConfig.java:859)     在   org.apache.kafka.streams.processor.internals.AbstractProcessorContext。(AbstractProcessorContext.java:59)     在   org.apache.kafka.streams.processor.internals.ProcessorContextImpl。(ProcessorContextImpl.java:42)     在   org.apache.kafka.streams.processor.internals.StreamTask。(StreamTask.java:134)     在   org.apache.kafka.streams.processor.internals.StreamThread $ TaskCreator.createTask(StreamThread.java:404)     在   org.apache.kafka.streams.processor.internals.StreamThread $ TaskCreator.createTask(StreamThread.java:365)     在   org.apache.kafka.streams.processor.internals.StreamThread $ AbstractTaskCreator.createTasks(StreamThread.java:350)     在   org.apache.kafka.streams.processor.internals.TaskManager.addStreamTasks(TaskManager.java:137)     在   org.apache.kafka.streams.processor.internals.TaskManager.createTasks(TaskManager.java:88)     在   org.apache.kafka.streams.processor.internals.StreamThread $ RebalanceListener.onPartitionsAssigned(StreamThread.java:259)     在   org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.onJoinComplete(ConsumerCoordinator.java:264)     在   org.apache.kafka.clients.consumer.internals.AbstractCoordinator.joinGroupIfNeeded(AbstractCoordinator.java:367)     在   org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureActiveGroup(AbstractCoordinator.java:316)     在   org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.poll(ConsumerCoordinator.java:295)     在   org.apache.kafka.clients.consumer.KafkaConsumer.pollOnce(KafkaConsumer.java:1146)     在   org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1111)     在   org.apache.kafka.streams.processor.internals.StreamThread.pollRequests(StreamThread.java:851)     ... 3更多原因:io.confluent.common.config.ConfigException:   缺少所需的配置“ schema.registry.url”,该配置没有   默认值。在   io.confluent.common.config.ConfigDef.parse(ConfigDef.java:243)在   io.confluent.common.config.AbstractConfig。(AbstractConfig.java:78)     在   io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig。(AbstractKafkaAvroSerDeConfig.java:61)     在   io.confluent.kafka.serializers.KafkaAvroSerializerConfig。(KafkaAvroSerializerConfig.java:32)     在   io.confluent.kafka.serializers.KafkaAvroSerializer.configure(KafkaAvroSerializer.java:48)     在   io.confluent.kafka.streams.serdes.avro.SpecificAvroSerializer.configure(SpecificAvroSerializer.java:58)     在   io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde.configure(SpecificAvroSerde.java:107)     在   org.apache.kafka.streams.StreamsConfig.defaultValueSerde(StreamsConfig.java:855)     ...还有19个

基于该错误,我认为我无法配置schema.registry.url来实现融合。 我快速浏览了示例here 在使用streamListener

对Spring Cloud Stream进行相同操作时有点失落

这是否需要单独配置?还是有一种方法可以在schema.registry.url本身中配置汇合正在寻找的application.yml

这是代码仓库https://github.com/naveenpop/springboot-kstream-confluent

更新1:

我应用了dturanski here的建议,错误消失了。但是,仍然无法将消息作为KStream<String, Organization>使用,在控制台中没有错误。

更新2:

应用了sobychacko here的建议,该消息可消耗,对象中的值为空。

我已经对GitHub示例进行了commit处理,以从spring boot本身生成消息,并且仍然将其作为空值获取。

感谢您的时间在此问题上。

2 个答案:

答案 0 :(得分:1)

尝试spring.cloud.stream.kafka.streams.binder.configuration.schema.registry.url: ...

答案 1 :(得分:1)

以下实现不会满足您的预期:

@StreamListener
    public void processOrganization(@Input(KstreamBinding.ORGANIZATION)KStream<String, Organization> organization) {
        log.info("Organization Received:" + organization);
 }

该日志语句在引导阶段仅被调用一次。为了使它起作用,您需要在收到的KStream上调用一些操作,然后在其中提供逻辑。例如我在foreach方法调用中提供lambda表达式的以下工作。

 @StreamListener
    public void processOrganization(@Input(KstreamBinding.ORGANIZATION) KStream<String, Organization> organization) {

        organization.foreach((s, organization1) -> log.info("Organization Received:" + organization1));
    }

配置中还存在一个问题,即您错误地将avro Serde分配给实际上是String的密钥。像这样更改它:

default:
                key:
                  serde: org.apache.kafka.common.serialization.Serdes$StringSerde
                value:
                  serde: io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde

有了这些更改,每次向主题发送内容时,我都会获得日志记录语句。但是,您的发送groovy脚本存在问题,我没有从您的Organization域中获取任何实际数据,但我会让您知道。

更新有关空Organization域对象的问题

之所以会发生这种情况,是因为您正在进行混合策略的混合模式。您正在使用生产者端但在Kafka Streams处理器上使用Confluent avro Serdes使用Spring Cloud Stream的avro消息转换器。从生产者到处理者,我一直尝试使用Confluent的序列化器,并且能够在出站上看到Organization域。这是修改后的配置,以使序列化保持一致。

spring:
  application:
    name: kstream
  cloud:
    stream:
      schemaRegistryClient:
        endpoint: http://localhost:8081
      schema:
        avro:
          schema-locations: classpath:avro/Organization.avsc
      bindings:
        organizationInput:
          destination: organization-updates
          group: demokstream.org
          consumer:
            useNativeDecoding: true
        organizationOutput:
          destination: organization-updates
          producer:
            useNativeEncoding: true
      kafka:
        bindings:
          organizationOutput:
            producer:
              configuration:
                key.serializer: org.apache.kafka.common.serialization.StringSerializer
                value.serializer: io.confluent.kafka.serializers.KafkaAvroSerializer
                schema.registry.url: http://localhost:8081
        streams:
          binder:
            brokers: localhost
            configuration:
              schema.registry.url: http://localhost:8081
              commit:
                interval:
                  ms: 1000
              default:
                key:
                  serde: org.apache.kafka.common.serialization.Serdes$StringSerde
                value:
                  serde: io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde

您还可以从主应用程序类中删除KafkaConfig类以及EnableSchemaRegistryClient批注。