web-dev-qa-db-fra.com

Print Kafka Stream Input out to console?

J'ai parcouru une grande partie de la documentation Kafka pour une application Java sur laquelle je travaille. J'ai essayé d'entrer dans la syntaxe lambda introduite in Java 8, mais je suis un peu sommaire sur ce terrain et je ne suis pas trop sûr que ce soit ce que j'utilise pour l'instant.

J'ai un service Kafka/Zookeeper fonctionnant sans aucun problème, et ce que je veux faire, c'est écrire un petit programme d'exemple qui, en fonction de l'entrée, l'écrira, mais ne fera pas de décompte de mots car il y a tellement d'exemples de déjà.

En ce qui concerne les exemples de données, je recevrai une chaîne de structure suivante:

Exemples de données

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

Question

Je souhaite pouvoir extraire les mots clés de 3 lettres et les imprimer avec un System.out.println. Comment obtenir une variable chaîne contenant l'entrée? Je sais comment appliquer des expressions régulières ou même simplement parcourir la chaîne pour obtenir les mots clés.

Code

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 = ?
}

J'ai zookeeper, kafka, producteur et consommateur fonctionnant tous connectés au même sujet, donc je veux essentiellement voir le même String apparaître sur toutes les instances (producteur, consommateur et flux).

12
Zeliax

Si vous utilisez Kafka Streams, vous devez appliquer des fonctions/opérateurs sur vos flux de données. Dans votre cas, vous créez un objet KStream, donc, vous voulez appliquer un opérateur à source.

Selon ce que vous voulez faire, il existe des opérateurs qui appliquent une fonction à chaque enregistrement du flux indépendamment (par exemple. map()), ou d'autres opérateurs qui appliquent une fonction à plusieurs enregistrements ensemble (par exemple. aggregateByKey()). Vous devriez jeter un œil à la documentation: http://docs.confluent.io/3.0.0/streams/developer-guide.html#kafka-streams-dsl et exemples https : //github.com/confluentinc/kafka-streams-examples

Ainsi, vous ne créez jamais de variables locales en utilisant Kafka Streams comme vous le montrez dans votre exemple ci-dessus, mais incorporez tout dans les opérateurs/fonctions qui sont enchaînés.

Par exemple, si vous souhaitez imprimer tous les enregistrements d'entrée sur stdout, vous pouvez faire

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);
    }
 });

Ainsi, après avoir démarré votre application via streams.start(), elle consomme les enregistrements de votre rubrique d'entrée et pour chaque enregistrement de votre rubrique, un appel à apply(...) est effectué, qui imprime l'enregistrement sur stdout.

Bien sûr, une façon plus native d'imprimer le flux sur la console serait d'utiliser source.print() (qui est fondamentalement la même que l'opérateur foreach() affiché avec un ForeachAction.)

Pour votre exemple avec l'attribution de la chaîne à une variable locale, vous devrez mettre votre code dans apply(...) et y faire vos trucs regex etc. pour "extraire les mots-clés à 3 lettres".

La meilleure façon d'exprimer cela serait cependant via une combinaison de flatMapValues() et print() (c'est-à-dire source.flatMapValues(...).print()). flatMapValues() est appelée pour chaque enregistrement d'entrée (dans votre cas, je suppose que la clé sera null pour que vous puissiez l'ignorer). Dans votre fonction flatMapValue, vous appliquez votre expression régulière et pour chaque correspondance, vous ajoutez la correspondance à une liste de valeurs que vous retournez finalement.

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;
    }
}

La sortie de flatMapValues sera à nouveau un KStream, contenant un enregistrement pour chaque mot clé trouvé (c'est-à-dire que le flux de sortie est une "union" sur toutes les listes que vous retournez dans ValueMapper#apply()). Enfin, vous imprimez simplement votre résultat sur la console via print(). (Bien sûr, vous pouvez également utiliser un seul foreach au lieu de flatMapValue + print mais ce serait moins modulaire.)

24
Matthias J. Sax