我正在尝试使用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
这是否需要单独配置?还是有一种方法可以在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本身生成消息,并且仍然将其作为空值获取。
感谢您的时间在此问题上。
答案 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
批注。