Spring Cloud Stream主题分区KStream读/写

时间:2019-02-26 14:57:01

标签: spring-cloud-stream

我有多个微服务,并且带有API,就像在同一个主题上为每个域事件在单独的分区上使用相同的主题一样,我能够配置spring kafka活页夹以使用

发送到不同的分区
spring.cloud.stream.bindings.<channel>.producer.partition-key- extractor-name= 

实施PartitionKeyExtractorStrategy

我的问题是我可以将Kstream绑定器配置为仅对@input和@Output进行用户分区吗?

到目前为止,我的理解是

spring.cloud.stream.kafka.streams.bindings.<channel>.producer.configuration.partitioner.class=

,但从未配置。如果还有其他方法或我犯了错误,请提出建议

1 个答案:

答案 0 :(得分:0)

您确定要将记录发送到某个分区吗?换句话说,您知道每个键的实际分区吗?如果仅提供PartitionKeyExtractorStrategy,则绑定器将任意选择一个分区来发送该记录。如果要使其具有确定性,则可以在生产者端提供一个partitionSelectorClass作为属性(实现接口PartitionSelectorStrategy)。该界面允许您根据密钥选择分区。假设您想将所有键为UUID-1的记录发送到分区1,并通过PartitionSelectorStrategy实现对其进行了编码。然后,这意味着您的kafka流处理器知道键为UUID-1的记录来自分区1。基于这些假设,您可以在kafka流处理器中执行以下操作。这基本上是为您的其他问题之一提供的this answer的变体。

@StreamListener("requesti")
@SendTo("responseo")
public KStream<UUID,Account> process(KStream<UUID, Account> events) {


        return  events.transform(() -> new Transformer<UUID, Account, KeyValue<UUID, Account>>() {
            ProcessorContext context;

            @Override
            public void init(ProcessorContext context) {
                this.context = context;
            }

            @Override
            public KeyValue<UUID,Account> transform(UUID key, Account value) {
                if (this.context.partition() == 1) {
                    //your processing logic
                    return KeyValue.pair(key, value);
                }
                return null;
            }

            @Override
            public void close() {

            }
        });
    }

使用上面的代码,您基本上可以在transform方法中过滤掉所有不相关的分区。仍然存在将出站数据发送到特定分区的问题。如果按原样使用上述代码,则活页夹会将数据发送到任意分区(尽管这可能是为活页夹添加的一项不错的功能)。但是,如果您希望出站记录位于确定性分区上,则可以在这种情况下直接使用Kafka Streams。见下文。

@StreamListener("requesti")
public void process(KStream<UUID, Account> events) {


    final KStream<UUID, Account> transformed = events.transform(() -> new Transformer<UUID, Account, KeyValue<UUID, Account>>() {
            ProcessorContext context;


            @Override
            public void init(ProcessorContext context) {
                this.context = context;
            }

            @Override
            public KeyValue<UUID, Account> transform(UUID key, Account value) {
                if (this.context.partition() == 1) {
                    //your processing logic
                    return KeyValue.pair(key, value);
                }
                return null;
            }

            @Override
            public void close() {

            }
        });


        transformed.to("outputTopic", Produced.with(new JsonSerde<>(), new JsonSerde<>(), new CustomStreamPartitioner()));
    }

    class CustomStreamPartitioner implements StreamPartitioner<UUID, Account> {

        @Override
        public Integer partition(String topic, UUID key, Account value, int numPartitions) {
            return 1; //change to the right partition based on the key.
        }
    }