web-dev-qa-db-ja.com

Print Kafka Stream Input out to console?

私はKafka私が取り組んでいるJavaアプリケーションのドキュメントを読みました。導入されたラムダ構文を調べてみましたJava 8ですが、私はその点で少し大ざっぱですが、今のところそれを使用する必要があると確信していません。

私は問題なく実行されているKafka/Zookeeperサービスを持っています。私がやりたいのは、入力に基づいてそれを書き出す小さなサンプルプログラムを書くことですが、すでに非常に多くの例があるので、ワードカウントは行いません。

サンプルデータについては、次の構造の文字列を取得します。

データの例

This a sample string containing some keywords such as GPS, GEO and maybe a little bit of ACC.

質問

3文字のキーワードを抽出してSystem.out.printlnで印刷できるようにしたい。入力を含む文字列変数を取得するにはどうすればよいですか?正規表現を適用する方法や、文字列を検索してキーワードを取得する方法さえ知っています。

コード

public static void main(String[] args) {
    Properties props = new Properties();
    props.put(StreamsConfig.APPLICATION_ID_CONFIG, "app_id");
    props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "0:0:0:0:0:0:0:1:9092");
    props.put(StreamsConfig.ZOOKEEPER_CONNECT_CONFIG, "0:0:0:0:0:0:0:1:2181");
    props.put(StreamsConfig.KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
    props.put(StreamsConfig.VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());

    final Serde<String> stringSerde = Serdes.String();

    KStreamBuilder builder = new KStreamBuilder();

    KStream<String, String> source = builder.stream(stringSerde, stringSerde, "in-stream");

    KafkaStreams streams = new KafkaStreams(builder, props);
    streams.start();

    //How do I assign the input from in-stream to the following variable?
    String variable = ?
}

私はすべて同じトピックに接続されているzookeeper、kafka、プロデューサー、およびコンシューマーを実行しているため、基本的にすべてのインスタンス(プロデューサー、コンシューマー、およびストリーム)に同じStringが表示されるようにしたいと思います。

12
Zeliax

Kafka Streamsを使用する場合は、データストリームに関数/演算子を適用する必要があります。この場合、KStreamオブジェクトを作成するため、sourceに演算子を適用します。

何をしたいかに応じて、ストリーム内の各レコードに関数を個別に適用する演算子(例:map())、または関数を複数のレコードに一緒に適用する他の演算子(例:aggregateByKey())。ドキュメントを確認する必要があります: http://docs.confluent.io/3.0.0/streams/developer-guide.html#kafka-streams-dsl と例 https ://github.com/confluentinc/kafka-streams-examples

したがって、上記の例に示すようにKafka Streamsを使用してローカル変数を作成するのではなく、連鎖する演算子/関数にすべてを埋め込みます。

たとえば、すべての入力レコードをstdoutに出力する場合は、次のようにします。

KStream<String, String> source = builder.stream(stringSerde, stringSerde, "in-stream");
source.foreach(new ForeachAction<String, String>() {
    void apply(String key, String value) {
        System.out.println(key + ": " + value);
    }
 });

したがって、streams.start()を介してアプリケーションを起動すると、入力トピックからのレコードが消費され、トピックの各レコードに対してapply(...)の呼び出しが行われ、標準出力にレコードが出力されます。

もちろん、ストリームをコンソールに出力するためのよりネイティブな方法は、source.print()を使用することです(これは、基本的には、すでにForeachActionが指定されたforeach()演算子と基本的に同じです)。

文字列をローカル変数に割り当てる例では、コードをapply(...)に入れ、そこに正規表現などを実行して「3文字のキーワードを抽出」する必要があります。

これを表現する最善の方法は、flatMapValues()print()の組み合わせ(つまり、source.flatMapValues(...).print())を使用することです。入力レコードごとにflatMapValues()が呼び出されます(あなたの場合、キーはnullであるため、無視できます)。 flatMapValue関数内で正規表現を適用し、一致ごとに、最終的に返される値のリストに一致を追加します。

source.flatMapValues(new ValueMapper<String, Iterable<String>>() {
    @Override
    public Iterable<String> apply(String value) {
        ArrayList<String> keywords = new ArrayList<String>();

        // apply regex to value and for each match add it to keywords

        return keywords;
    }
}

flatMapValuesの出力は、再びKStreamになり、見つかった各キーワードのレコードが含まれます(つまり、出力ストリームは、ValueMapper#apply()で返すすべてのリストの「和集合」です)。最後に、print()を使用して結果をコンソールに出力します。 (もちろん、foreach + flatMapValueの代わりに単一のprintを使用することもできますが、これはモジュール性が低くなります。)

24
Matthias J. Sax