簡體   English   中英

如何為kafka流使用同一主題的多個轉換器?

[英]How to use multiple transformers using the same topic for kafka streams?

我需要使用多個轉換器解析 kafka 上的復雜消息。 每個轉換器解析消息的一部分,並通過在消息上填充一些屬性來編輯消息。 最后,完全解析的消息使用 Kafka 消費者存儲在數據庫中。 目前,我正在這樣做:

streamsBuilder.stream(Topic.A, someConsumer)
       \\ filters messages that have unparsed parts of type X
       .filter(filterX)
       \\ transformer that edits the message and produces new Topic.E messages
       .transform(ParseXandProduceE::new)
       .to(Topic.A, someProducer)

streamsBuilder.stream(Topic.A, someConsumer)
       \\ filters messages that have unparsed parts of type Y
       .filter(filterY)
       \\ transformer that edits the message and produces new Topic.F messages
       .transform(ParseYandProduceF::new)
       .to(Topic.A, someProducer)

變壓器看起來像:

class ParseXandProduceE implements Transformer<...> {
    @Override
    public KeyValue<String, Message> transform (String key, Message message) {
           message.x = parse(message.rawX);
           context.forward(newKey, message.x, Topic.E);
           return KeyValue.pair(key, message);
    }
}

然而,這很麻煩,相同的消息在這些流中流動多次。 此外,還有一個消費者將topic.A的消息存儲在數據庫中。 消息當前存儲多次,在每次轉換之前和每次轉換之后。 有必要將每條消息存儲一次。

以下可能有效,但似乎不利,因為每個過濾器+轉換塊都可以干凈地放在其自己的單獨 class 中:

streamsBuilder.stream(Topic.A, someConsumer)
       \\ transformer that filters and edits the message and produces new Topic.E + Topic.F messages
       .transform(someTransformer)
       .to(Topic.B, someProducer)

並讓持久性消費者聽Topic.B

后者提出的解決方案是go,還是有其他方法可以達到相同的結果? 也許有源和匯的完整拓撲配置? 如果是這樣,這種情況會是什么樣子?

使用單個變壓器似乎是最簡單的解決方案。 因為您有兩個獨立的過濾器,所以如果您嘗試鏈接各個運算符,程序將變得更加復雜。 如果您知道每條消息只會通過一個過濾器,而不會同時通過兩個過濾器,則可以使用branch()

KStream[] subStreams = stream.branch(new Predicates[]{filterX,filterY});

subStream[0].transform(ParseXandProduceE::new)
            .merge(subStream[1].transform(ParseYandProduceF::new)
            .to(...)

請注意,上述解決方案僅在兩個轉換器都不需要轉換任何消息時才有效( branch()將每條消息放入第一個匹配謂詞的分支中,但絕不會放入多個分支中)。 因此,如果一條消息可以通過兩個過濾器,則您需要做一些更復雜的事情:

KStream[] subStreams = stream.branch(new Predicates[]{filterX,filterY});

KStream passedX = subStreams[0];
KStream transformedXE = passedX.transform(ParseXandProduceE::new);

// a message that passed filterX may also pass filterY,
// and thus we merge those message back to the "y-stream"
// (of course, those messages would already be transformed by `ParseXandProduceE`)
KStream passedY = subStream[1].merge(transformedXE.filter(filterY);

// the result contains all message that only pass filterX and got transformed,
// plus all messages that passed filterY (and maybe also filterX) and got transformed
KStream result = transformedXE.filterNot(filterY)
                              .merge(passedY.transform(ParseYandProduceF::new)

result.to(...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM