Mise en route du traitement de flux avec le flux de données Spring Cloud

1. Introduction

Spring Cloud Data Flow est un modèle de programmation et d’exploitation natif au cloud pour les microservices de données composables.

Avec Spring Cloud Data Flow , les développeurs peuvent créer et orchestrer des pipelines de données pour des cas d’utilisation courants tels que l’acquisition de données, l’analyse en temps réel et l’importation/exportation de données. .

Il existe deux types de pipelines de données, les pipelines de données en continu et en mode batch.

Dans le premier cas, une quantité illimitée de données est consommée ou produite via un middleware de messagerie. Dans le second cas, la tâche de courte durée traite un ensemble fini de données puis se termine.

Cet article portera sur le traitement en continu.

2. Aperçu architectural

Les principaux composants de ce type d’architecture sont Applications , le Data Flow Server et le moteur d’exécution cible.

De plus, en plus de ces composants clés, nous avons généralement un Data Flow Shell et un message broker dans l’architecture.

Voyons tous ces composants plus en détail.

2.1. Applications

En règle générale, un pipeline de diffusion de données en continu inclut la consommation d’événements provenant de systèmes externes, le traitement de données et la persistance polyglotte. Ces phases sont communément appelées Source , Processor et Sink dans la terminologie Spring Cloud :

  • La source:

  • Processeur: utilise les données de la Source , effectue certains traitements sur

et émet les données traitées vers la prochaine application en cours Sink: ** soit consomme d’un Source ou Processor et écrit

données dans la couche de persistance souhaitée

Ces applications peuvent être empaquetées de deux manières:

  • Spring Boot uber-jar hébergé dans un référentiel Maven, fichier, http

ou toute autre implémentation de ressource Spring (cette méthode sera utilisée dans Cet article) ** Docker

De nombreuses sources, processeurs et applications de stockage pour les cas d’utilisation courants (par exemple, jdbc, hdfs, http, routeur) sont déjà fournis et prêts à être utilisés par l’équipe Spring Cloud Data Flow .

** 2.2. Runtime

**

En outre, un environnement d’exécution est nécessaire à l’exécution de ces applications. Les runtimes supportés sont:

  • Fonderie Cloud

  • Apache YARN

  • Kubernetes

  • Apache Mesos

  • Serveur local pour le développement (qui sera utilisé dans cet article)

** 2.3. Serveur de flux de données

**

Le composant responsable du déploiement d’applications sur un environnement d’exécution est le Data Flow Server . Un fichier jar exécutable Data Flow Server est fourni pour chaque environnement d’exécution cible.

Le serveur de flux de données est responsable de l’interprétation:

  • Un flux DSL qui décrit le flux logique de données à travers plusieurs

applications.

  • Un manifeste de déploiement décrivant le mappage des applications sur

le runtime.

2.4. Flux de données Shell

Data Flow Shell est un client pour le serveur de flux de données.

Par exemple, le DSL décrivant le flux de données d’une source http vers un récepteur jdbc serait écrit comme suit: «http | jdbc ”. Ces noms dans la DSL sont enregistrés auprès de Data Flow Server et correspondent à des artefacts d’application pouvant être hébergés dans des référentiels Maven ou Docker.

Spring propose également une interface graphique, nommée Flo , permettant de créer et de surveiller des pipelines de données en continu. Cependant, son utilisation est en dehors de la discussion de cet article.

** 2.5. Message Broker

**

Comme nous l’avons vu en section, nous avons utilisé le symbole de canal dans la définition du flux de données. Le symbole de canal représente la communication entre les deux applications via un middleware de messagerie.

Les deux courtiers middleware de messagerie pris en charge sont les suivants:

  • Apache Kafka

  • RabbitMQ

Et maintenant, maintenant que nous avons un aperçu des composants architecturaux - il est temps de construire notre premier pipeline de traitement de flux.

** 3. Installer un courtier de messages

**

Comme nous l’avons vu, les applications en cours de développement ont besoin d’un middleware de messagerie pour communiquer. Pour les besoins de cet article, nous utiliserons RabbitMQ .

Pour plus de détails sur l’installation, suivez les instructions du site officiel .

4. Le serveur de flux de données local

Pour accélérer le processus de génération de nos applications, nous utiliserons Spring Initializr ; avec son aide, nous pouvons obtenir nos applications Spring Boot en quelques minutes.

Après avoir atteint le site Web, choisissez simplement un Group et un nom Artifact .

Une fois cela fait, cliquez sur le bouton Générer un projet pour lancer le téléchargement de l’artefact Maven.

Une fois le téléchargement terminé, décompressez le projet et importez-le en tant que projet Maven dans votre IDE de choix.

Ajoutons une dépendance Maven au projet. Comme nous aurons besoin des bibliothèques Dataflow Local Server , ajoutons le spring-cloud-starter-dataflow-server-local dépendance:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-dataflow-server-local</artifactId>
</dependency>

Nous devons maintenant annoter la classe principale Spring Boot avec l’annotation @ EnableDataFlowServer :

@EnableDataFlowServer
@SpringBootApplication
public class SpringDataFlowServerApplication {

    public static void main(String[]args) {
        SpringApplication.run(
          SpringDataFlowServerApplication.class, args);
    }
}

C’est tout. Notre Local Data Flow Server est prêt à être exécuté:

mvn spring-boot:run

L’application démarrera sur le port 9393.

5. Le shell de flux de données

Encore une fois, allez à l’initialisation du printemps et choisissez un nom de groupe et d’artifact.

Une fois le projet téléchargé et importé, ajoutons une dépendance spring-cloud-dataflow-shell :

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dataflow-shell</artifactId>
</dependency>

Nous devons maintenant ajouter l’annotation @ EnableDataFlowShell à la classe principale Spring Boot :

@EnableDataFlowShell
@SpringBootApplication
public class SpringDataFlowShellApplication {

    public static void main(String[]args) {
        SpringApplication.run(SpringDataFlowShellApplication.class, args);
    }
}

Nous pouvons maintenant lancer le shell:

mvn spring-boot:run

Une fois le shell en cours d’exécution, vous pouvez taper la commande help dans l’invite pour afficher la liste complète des commandes pouvant être exécutées.

6. L’application source

De même, sur Initializr, nous allons maintenant créer une application simple et ajouter une dépendance Stream Rabbit appelée https://search.maven.org/search?q=a:spring-cloud-stoud-stream-rabbit lapin de départ:]

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

Nous ajouterons ensuite l’annotation @ EnableBinding (Source.class) à la classe principale Spring Boot :

@EnableBinding(Source.class)
@SpringBootApplication
public class SpringDataFlowTimeSourceApplication {

    public static void main(String[]args) {
        SpringApplication.run(
          SpringDataFlowTimeSourceApplication.class, args);
    }
}

Nous devons maintenant définir la source des données à traiter.

Cette source pourrait être toute charge de travail potentiellement illimitée (données de capteur d’Internet des objets, traitement des événements 24 heures sur 24, 7 jours sur 7, acquisition de données de transaction en ligne).

  • Dans notre exemple d’application, nous produisons un événement (pour simplifier un nouvel horodatage) toutes les 10 secondes avec un Poller .

L’annotation @ InboundChannelAdapter envoie un message au canal de sortie de la source, en utilisant la valeur de retour comme charge utile du message:

@Bean
@InboundChannelAdapter(
  value = Source.OUTPUT,
  poller = @Poller(fixedDelay = "10000", maxMessagesPerPoll = "1")
)
public MessageSource<Long> timeMessageSource() {
    return () -> MessageBuilder.withPayload(new Date().getTime()).build();
}

Notre source de données est prête.

** 7. L’application du processeur

**

Ensuite, nous allons créer une application et ajouter une dépendance Stream Rabbit .

Nous ajouterons ensuite l’annotation @ EnableBinding (Processor.class) à la classe principale Spring Boot :

@EnableBinding(Processor.class)
@SpringBootApplication
public class SpringDataFlowTimeProcessorApplication {

    public static void main(String[]args) {
        SpringApplication.run(
          SpringDataFlowTimeProcessorApplication.class, args);
    }
}

Ensuite, nous devons définir une méthode pour traiter les données provenant de l’application source.

Pour définir un transformateur, nous devons annoter cette méthode avec @ Transformer annotation:

@Transformer(inputChannel = Processor.INPUT,
  outputChannel = Processor.OUTPUT)
public Object transform(Long timestamp) {

    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:yy");
    String date = dateFormat.format(timestamp);
    return date;
}

Il convertit un horodatage du canal "d’entrée" en une date formatée qui sera envoyée au canal "de sortie".

** 8. L’application de l’évier

**

  • La dernière application à créer est l’application Sink. **

Encore une fois, allez à Spring Initializr et choisissez un Group , un nom Artifact . Après avoir téléchargé le projet, ajoutons une dépendance Stream Rabbit .

Ajoutez ensuite l’annotation @ EnableBinding (Sink.class) à la classe principale Spring Boot :

@EnableBinding(Sink.class)
@SpringBootApplication
public class SpringDataFlowLoggingSinkApplication {

    public static void main(String[]args) {
    SpringApplication.run(
          SpringDataFlowLoggingSinkApplication.class, args);
    }
}

Nous avons maintenant besoin d’une méthode pour intercepter les messages provenant de l’application processeur.

Pour ce faire, nous devons ajouter l’annotation @ StreamListener (Sink.INPUT) à notre méthode:

@StreamListener(Sink.INPUT)
public void loggerSink(String date) {
    logger.info("Received: " + date);
}

La méthode affiche simplement l’horodatage transformé en une date formatée dans un fichier journal.

** 9. Enregistrer une application de flux

**

Spring Cloud Data Flow Shell nous permet d’enregistrer une application Stream avec le registre des applications à l’aide de la commande app register .

Nous devons fournir un nom unique, un type d’application et un URI pouvant être résolus pour l’artefact de l’application. Pour le type, spécifiez “ source “, “ processor “ ou “ sink “.

Lorsque vous fournissez un URI avec le schéma maven, le format doit être conforme à ce qui suit:

maven://<groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>

Pour enregistrer les applications Source , Processor et Sink , accédez à Spring Cloud Data Flow Shell et exécutez les commandes suivantes à l’invite:

app register --name time-source --type source
  --uri maven://org.baeldung.spring.cloud:spring-data-flow-time-source:jar:0.0.1-SNAPSHOT

app register --name time-processor --type processor
  --uri maven://org.baeldung.spring.cloud:spring-data-flow-time-processor:jar:0.0.1-SNAPSHOT

app register --name logging-sink --type sink
  --uri maven://org.baeldung.spring.cloud:spring-data-flow-logging-sink:jar:0.0.1-SNAPSHOT

10. Créer et déployer le flux

Pour créer une nouvelle définition de flux, accédez au shell de flux de données __Spring Cloud et exécutez la commande shell suivante:

stream create --name time-to-log
  --definition 'time-source | time-processor | logging-sink'

Ceci définit un flux nommé time-to-log basé sur l’expression DSL time-source | processeur de temps | logging-sink’ .

Ensuite, pour déployer le flux, exécutez la commande shell suivante:

stream deploy --name time-to-log

Data Flow Server résout time-source , time-processor et logging-sink en coordonnées maven et les utilise pour lancer les applications time-source , time-processor et logging-sink du flux.

Si le flux déployé, vous verrez dans les journaux Data Flow Server que les modules ont été démarrés et liés entre eux:

2016-08-24 12:29:10.516  INFO 8096 ---[io-9393-exec-10]o.s.c.d.spi.local.LocalAppDeployer: deploying app time-to-log.logging-sink instance 0
   Logs will be in PATH__TO__LOG/spring-cloud-dataflow-1276836171391672089/time-to-log-1472034549734/time-to-log.logging-sink
2016-08-24 12:29:17.600  INFO 8096 ---[io-9393-exec-10]o.s.c.d.spi.local.LocalAppDeployer       : deploying app time-to-log.time-processor instance 0
   Logs will be in PATH__TO__LOG/spring-cloud-dataflow-1276836171391672089/time-to-log-1472034556862/time-to-log.time-processor
2016-08-24 12:29:23.280  INFO 8096 ---[io-9393-exec-10]o.s.c.d.spi.local.LocalAppDeployer       : deploying app time-to-log.time-source instance 0
   Logs will be in PATH__TO__LOG/spring-cloud-dataflow-1276836171391672089/time-to-log-1472034562861/time-to-log.time-source

** 11. Révision du résultat

**

Dans cet exemple, la source envoie simplement l’horodatage actuel sous forme de message chaque seconde, le processeur le formate et le collecteur de journal génère l’horodatage formaté à l’aide de la structure de journalisation.

Les fichiers journaux se trouvent dans le répertoire affiché dans la sortie du journal du Data Flow Server , comme indiqué ci-dessus. Pour voir le résultat, nous pouvons suivre le journal:

tail -f PATH__TO__LOG/spring-cloud-dataflow-1276836171391672089/time-to-log-1472034549734/time-to-log.logging-sink/stdout__0.log
2016-08-24 12:40:42.029  INFO 9488 ---[r.time-to-log-1]s.c.SpringDataFlowLoggingSinkApplication : Received: 2016/08/24 11:40:01
2016-08-24 12:40:52.035  INFO 9488 ---[r.time-to-log-1]s.c.SpringDataFlowLoggingSinkApplication : Received: 2016/08/24 11:40:11
2016-08-24 12:41:02.030  INFO 9488 ---[r.time-to-log-1]s.c.SpringDataFlowLoggingSinkApplication : Received: 2016/08/24 11:40:21

12. Conclusion

Dans cet article, nous avons vu comment créer un pipeline de données pour le traitement de flux en utilisant Spring Cloud Data Flow .

Nous avons également vu le rôle des applications Source , Processor et Sink dans le flux et la manière de brancher et de lier ce module dans un Data Flow Server via l’utilisation de Data Flow Shell .

L’exemple de code se trouve dans le projet GitHub