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:
This a sample string containing some keywords such as GPS, GEO and maybe a little bit of ACC.
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.
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).
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.)