Modèles de conception des jobs Talend et bonnes pratiques : 4e partie

Notre étude des modèles de conception des jobs Talend et bonnes pratiques arrive à un tournant. Ma modeste contribution à la création de contenu utile à tous a donné naissance à de nouveaux projets. Suite au succès des précédents articles de cette série (lisez les 1re partie, 2e partie et 3e partie si ce n'est pas déjà fait) et des événements Technical Boot Camp (merci à tous ceux que j'ai rencontrés à cette occasion), et au vu des retours positifs lorsque ces contenus ont été présentés directement à des clients, nous avons décidé en interne de procéder à des changements. Nous allons créer et mettre à disposition plusieurs webinars sur ce thème. Je vous demande un peu de patience, car tout cela demande du temps et des ressources, mais nous espérons que le premier webinar sera disponible en début d'année 2017. En attendant, je me réjouis de vous proposer un nouvel article, en espérant qu'il vous sera utile !

Voici donc comme promis plusieurs bonnes pratiques supplémentaires pour les modèles de conception de jobs avec Talend. Laissez-moi tout d'abord vous rappeler un point simple, mais souvent méconnu. Talend est un générateur de code Java : définir des directives de développement fortifie et simplifie le code Java généré via les modèles de conception des jobs. Cela semble évident, mais des jobs bien conçus, générant du code Java propre grâce à ces concepts, sont le meilleur moyen d'atteindre vos objectifs. Je les appelle des projets programmés pour réussir.

Projets Talend programmés pour réussir

Cela peut être extrêmement simple de créer des jobs Talend... Mais les jobs peuvent aussi devenir très complexes. Le secret de la réussite, c'est d'adopter les bonnes habitudes et la discipline nécessaires, et de les adapter aux besoins de chaque projet.

Des préceptes fondamentaux présentés au début de cette série jusqu'à maintenant, mon objectif a toujours été d'encourager la discussion autour de ces bonnes pratiques, pour parvenir à créer des modèles de conception des jobs solides et utiles sur Talend. Une conception de jobs atomique et une orchestration parent/enfant sont bénéfiques pour la plupart des cas d'usage. Et lorsque les projets peuvent tirer parti de code réutilisable, cela accélère leur réussite. Bien sûr, vous restez maitre de vos choix. Je vous demande néanmoins une seule chose : soyez cohérent !

Cycle de vie du développement des bases de données (DDLC)

Attendez. Et qu'en est-il des données ? Après tout, nous traitons des données. La majeure partie de ces données réside dans des bases de données. Avons-nous besoin de bonnes pratiques pour les bases de données ? Est-ce une simple question rhétorique ? Les modèles de données (schémas) changent avec le temps, la conception des bases de données doit donc avoir son propre cycle de vie ! Cela paraît logique.

Les bases de données évoluent, c'est un fait dont nous, les développeurs, devons tenir compte. Nous avons intégré le processus SDLC, nous devrions donc facilement accepter d'avoir également besoin d'un cycle de vie du développement des bases de données. Cela me semble assez évident. Pour tout environnement (DEV/TEST/PROD), une base de données doit accepter :

  • Une nouvelle INSTALLATIONen fonction de la version actuelle du schéma
  • L'application d'une MISE À JOURdépôt/création/modification des objets de base de données en passant d'une version à la suivante
  • La MIGRATION de donnéessi une « mise à niveau » perturbatrice a lieu (comme le fractionnement de tables)

Comprendre le cycle de vie des bases de données et son impact sur la conception des jobs est de plus en plus important. Il est donc essentiel de gérer correctement les versions de votre modèle de base de données. Suivez un processus de conception recommandé. Utilisez des graphiques pour illustrer les conceptions. Créez un dictionnaire ou un glossaire des données, et gardez une trace du lignage des modifications historiques. Je proposerai bientôt un nouvel article spécifique sur ce sujet. En attendant, suivez le processus ci-dessous lorsque vous créez des modèles de bases de données. Ҫa demande plus de discipline, mais ça marche !

Plus de bonnes pratiques en matière de conception des jobs

Voici de nouveaux modèles de conception des jobs et bonnes pratiques à découvrir. Ils font appel à des fonctionnalités Talend plus pointues, que vous utilisez peut-être moins souvent. J'espère que vous les trouverez utiles.

Huit bonnes pratiques supplémentaires :

Références (lookups) tMap

Comme beaucoup d'entre vous le savent déjà, le composant de base tMap est très utilisé dans les jobs Talend, en raison de ses puissantes capacités de transformation.

L'utilisation la plus fréquente de ce composant tMap est le mapping d'un schéma de flux de données, d'une entrée source vers une sortie cible. C'est simple, non ? Nous pouvons également incorporer plusieurs flux de données de schémas sources et cibles, ce qui nous permet de lier ou de diviser ces flux de données comme nous le souhaitons, et d'incorporer si nécessaire des expressions de transformation contrôlant la dispersion en aval des données entrantes. Les expressions au sein d'un composant tMap peuvent être appliquées sur le schéma source ou le schéma cible. Elles peuvent également avoir recours à des variables définies au sein du composant tMap. Pour en savoir plus, consultez le guide Talend Components Reference Guide. Rappelez-vous simplement ceci : un grand pouvoir implique de grandes responsabilités.

Une autre utilisation très intéressante du composant tMap consiste à incorporer des références (ou « lookups ») liées avec le flux de données source. Il n'y a pas de limite réelle au nombre de références que vous pouvez appliquer à un composant tMap ou à ce qu'incluent les données de références, mais vous devez tenir compte de certains aspects pratiques.

Prenons un exemple simple : deux générateurs de lignes, l'un est la source et l'autre la référence. Au moment de l'exécution, les données de référence sont générées, avant que les données sources ne soient traitées.

Le paramètre de jointure des données de référence étant défini sur Load Once (Charge une fois), tous les enregistrements sont chargés en mémoire puis traités par rapport à l'ensemble de résultats des données sources. Ce comportement par défaut offre des jointures hautes performances et peut être très efficace. 

Vous pouvez cependant aussi imaginer que lors du chargement de millions de lignes de référence ou de douzaines de colonnes, les exigences en matière de mémoire sont énormes. Que se passe-t-il alors si plusieurs références contenant chacune des millions de lignes sont nécessaires ? Quelle quantité de mémoire faudra-t-il ? Réfléchissez bien à vos références lorsqu'elles impliquent de nombreux enregistrements ou des centaines de colonnes.

Envisageons un compromis : mémoire contre performance. Trois modèles de références sont disponibles :

  • Load Once (Charge une fois) - lit tous les enregistrements répondant aux critères en mémoire
  • Reload at each Row (Recharge à chaque ligne)- lit uniquement la ligne répondant aux critères pour chaque enregistrement source
  • Reload at each Row (cache) (Recharge à chaque ligne (cache)) - lit uniquement la ligne répondant aux critères pour chaque enregistrement source et la met en cache

La vitesse est l'avantage indéniable du chargement en mémoire des données de référence pour une jointure avec la source. Cependant, si des contraintes de mémoire interdisent les volumes importants de données de référence, ou si vous ne souhaitez tout simplement pas charger TOUTES les données de référence car cela n'est pas nécessaire pour votre cas d'usage, utilisez le modèle de référence Reload at each Row (Recharge à chaque ligne). Il y a une astuce à connaître pour que cela marche.

Tout d'abord, dans le composant tMap, changez le mode de référence en Read at each Row (Lire à chaque ligne). Notez que la zone en dessous s'ouvre pour vous permettre d'entrer la (les) clé(s) dont vous avez besoin. Ajoutez les clés, qui définissent les variables globales disponibles en dehors du composant tMap.

Pour le composant de référence, utilisez la fonction (datatype)globalMap.get(“key”) dans la clause WHERE de votre syntaxe SQL pour appliquer la valeur de clé enregistrée définie dans tMap pour le dataset de référence. Cela permet de terminer la récupération de référence pour chaque enregistrement traité depuis la source.

Et voilà, vos références sont en place et fonctionnent !

Variables globales

Les variables globales peuvent avoir des définitions et des utilisations variées. Les développeurs en créent et en utilisent constamment dans les jobs Talend, et elles sont alors appelées variables contextuelles. Elles sont parfois Built-In (intégrées), c'est-à-dire appartenant localement à un job, et parfois présentes dans le Référentiel de projet en tant que Groupes contextuels, ce qui permet de les réutiliser pour plusieurs jobs.

Ce sont toutes des variables globales, dont la valeur est
déterminée au moment de l'exécution et qui peuvent être utilisées dans l'ensemble du job qui les définit. Vous savez que vous utilisez une variable globale si vous voyez un élément context.varname inclus dans un composant, une expression ou un déclencheur. N'oubliez pas de placer les variables fréquemment utilisées dans un projet de référence pour augmenter leur utilisation dans plusieurs projets.

Talend propose également des composants tSetGlobalVar et tGlobalVarLoad, qui peuvent définir, stocker et utiliser des variables globales à l'exécution. Le composant tSetGlobalVar stocke une paire clé-valeur dans les jobs, ce qui équivaut à utiliser une variable contextuelle avec un meilleur contrôle (comme la gestion des erreurs). Regardez l'exemple ci-dessous où une seule valeur MAX(date) est récupérée, puis utilisée dans une requête SQL pour filtrer la deuxième récupération d'un ensemble d'enregistrements.

Pour accéder à la variable globale, utilisez la fonction (datatype)globalMap.get(“key”) dans la clause SQL WHERE. Retenez bien cette fonction, vous l'utiliserez sûrement très souvent lorsque vous aurez constaté à quel point elle est utile !

Le composant tGlobalVarLoad offre des capacités similaires pour les jobs de big data pour lesquels le composant tSetGlobalVar n'est pas disponible. Regardez mon exemple où une valeur agrégée est calculée, puis utilisée dans une lecture suivante pour déterminer quels enregistrements doivent être renvoyés.

Nous n'en avons pas encore tout à fait terminé avec ce sujet. Il existe également des variables globales système, disponibles dans un job et dont les valeurs sont déterminées par les composants eux-mêmes. Nous avons évoqué l'une d'entre elles dans le premier article de cette série, en parlant de la bonne pratique pour la gestion des erreurs : CHILD_RETURN_CODE et ERROR_MESSAGE. Ces variables globales système sont en général disponibles immédiatement après que l'exécution d'un composant a défini leur valeur. Selon le composant, différentes variables système sont disponibles. En voici quelques-unes :

  • ERROR_MESSAGE / DIE_MESSAGE / WARN_MESSAGE
  • CHILD_RETURN_CODE / DIE_CODE / WARN_CODE / CHILD_EXCEPTION_STACK
  • NB_LINE / NB_LINE_OK / NB_LINE_REJECT
  • NB_LINE_UPDATED / NB_LINE_INSERTED / NB_LINE_DELETED
  • global.projectName / global.jobName (variables de niveau système, leur utilisation est évidente)

Chargement de contextes

Les groupes contextuels permettent des conceptions de jobs hautement réutilisables, mais certains cas nécessitent encore plus de flexibilité. Par exemple, supposons que vous souhaitiez gérer les valeurs par défaut des variables contextuelles en externe. Il est en effet parfois plus pratique de les enregistrer dans un fichier ou même une base de données. Gérer leurs valeurs en externe peut être très efficace et même aider à résoudre certains problèmes de sécurité. C'est exactement ce que permet de faire le composant tContextLoad.

L'exemple ci-dessus illustre une manière simple de concevoir votre job pour qu'il initialise les variables contextuelles à l'exécution. Le fichier externe utilisé pour le chargement contient des paires clé-valeur nommées délimitées par des virgules. Lorsqu'il est lu, il remplace les valeurs actuelles des variables contextuelles définies dans le job. Dans ce cas, les informations de connexion de la base de données sont chargées pour assurer une connexion correcte. Notez que vous avez le contrôle de certains éléments de gestion des erreurs, ce qui permet un arrêt immédiat du job de manière programmée : Die on Error. Les cas dans lesquels cela est possible sont rares et précieux. Bien sûr, le composant tContextLoad peut très facilement utiliser une requête de base de données, et je connais plusieurs clients qui utilisent cette fonctionnalité.

Un composant correspondant tContextDump est disponible, qui écrit en sortie les variables contextuelles actuelles dans un fichier ou une base de données. Il peut servir pour les jobs hautement adaptables.

Utilisation de schémas dynamiques

On me demande souvent comment concevoir des jobs compatibles avec les schémas dynamiques. C'est une question piège, car les schémas dynamiques sont utilisés dans de nombreux cas d'usage. Le cas le plus courant est sans doute celui où les données de plusieurs tables doivent être migrées vers un jeu de tables correspondant, parfois dans un système de base de données différent (par exemple, d'Oracle à MS SQL Server). Créer un job pour déplacer ces données est assez simple, mais presque immédiatement nous réalisons que créer un job pour chaque table n'est pas envisageable. Imaginez s'il y a des centaines de tables ! N'est-il pas possible de créer un seul job qui gère TOUTES les tables ? Malheureusement, ce n'est pas possible dans Talend. Mais ne soyez pas déçus, DEUX jobs suffisent : un pour vider les données et un autre pour charger les données. Cela vous convient ?

Voici un exemple de job. Il établit trois connexions : les deux premières récupèrent les listes TABLE et COLUMN (colonne), et la troisième récupère les données elles-mêmes. Avec une itération sur chaque table, en enregistrant les colonnes, je peux lire et écrire des données dans un fichier positionnel non relationnel (processus de vidage DUMP) en utilisant le composant tSetDynamicSchema. Un job similaire ferait la même chose à la différence que la troisième connexion lirait le fichier positionnel et écrirait dans le magasin de données cible (processus de chargement LOAD).

Dans ce scénario, les développeurs doivent comprendre le fonctionnement interne de leur base de données hôte. La plupart des systèmes tels qu'Oracle, MS SQL Server et MySQL ont des tables système, souvent appelées schéma d'information, contenant des métadonnées d'objet sur une base de données, dont des tables et leurs colonnes. Voici une requête qui extrait une table/liste de colonnes complète de ma base de données TAC v6.1 MySQL (est-ce que la mise en forme de ma syntaxe SQL vous plaît ?) :

Vous devez utiliser des identifiants de connexion disposant de permissions SELECT (Sélectionner) pour cette base de données habituellement protégée.

Notez que j'utilise un composant tJavaFlex pour itérer les noms de table trouvés. J'enregistre chaque valeur Table Name (Nom de table) et définit un indicateur Control Break (Arrêt du contrôle), puis itère chaque table trouvée et récupère sa liste de colonnes triée. Une fois les éventuelles valeurs « null » ajustées pour les longueurs de colonnes, le schéma dynamique enregistré est terminé. L'élément conditionnel « IF » (Si) vérifie l'indicateur Control Break (Arrêt du contrôle) lorsque le nom de la table change, et commence le processus de vidage de la table actuelle. Et le tour est joué !

Composants SQL dynamiques

Le code dynamique, c'est fantastique ! Talend vous permet d'utiliser du code dynamique de plusieurs façons. Dans la conception de jobs précédente, j'ai utilisé une approche directe pour récupérer les listes de tables et de colonnes depuis une base de données. Talend propose des composants spécifiques à chaque système hôte pour faire la même chose. Ces composants t{DB}TableList et t{DB}ColumnList (où {DB} est le nom du composant hôte) offrent un accès direct aux métadonnées du schéma d'information, sans avoir à connaître l'hôte. Il est possible d'utiliser ces composants pour les processus DUMP/LOAD décrits ci-dessus, mais c'est moins amusant !

Toutes les requêtes SQL ne sont pas conçues pour récupérer ou stocker des données. Certains effectuent d'autres opérations de bases de données. Dans ce cas, utilisez les composants t{DB}Row et t{DB}SP. Le premier vous permet d'exécuter presque toutes les requêtes SQL qui ne renvoient pas de jeu de résultats, par exemple DROP TABLE. Le deuxième permet d'exécuter une procédure stockée.

Et enfin, le composant t{DB}LastInsertId récupère l'ID le plus récent depuis un composant de sortie de base de données. Il est parfois bien utile.

CDC

Une autre question fréquente est celle-ci : Talend est-il compatible avec CDC (Change Data Capture, Modifier la capture des données) ? La réponse est OUI bien sûr : grâce à des mécanismes de Publication/Abonnement (Publish/Subscribe) directement liés au système de base de données hôte. Notez bien que certains systèmes de base de données ne sont pas compatibles avec CDC. Voici la liste actuelle des systèmes compatibles avec CDC dans les jobs Talend :

Trois modes CDC sont disponibles :

  • Trigger (par défaut) - utilise des déclencheurs hôtes de bases de données qui suivent les insertions, mises à jour et suppressions
  • Redo/Archive Log - utilisé avec Oracle 11g et versions antérieures uniquement
  • XStream - utilisé avec Oracle 12 et OCI uniquement

Puisque vous utiliserez a priori principalement le mode Trigger, examinons en détail son architecture :

Le Guide utilisateur Talend, chapitre 11 explique clairement le processus CDC, sa configuration, et son utilisation avec Studio et en coordination avec votre système de base de données hôte. Bien que cela soit très simple en théorie, une configuration assez longue est nécessaire. Étudiez très sérieusement vos besoins, vos modes CDC et vos paramètres de conception des jobs à l'avance, et surtout détaillez-les bien dans vos directives de développement.

Une fois l'environnement CDC établi, il offre un mécanisme robuste pour mettre à jour les cibles en aval (en général un data warehouse). Utilisez les composants t{DB}CDC dans vos jobs Talend pour extraire les données modifiées depuis la dernière extraction. Certes, la configuration et la mise en route de CDC demandent du temps et une réelle implication, mais cela en vaut la peine !

Composants personnalisés

Bien que Talend propose plus de 1 000 composants, vous pouvez tout de même avoir besoin de créer votre propre composant. Les développeurs Talend intègrent souvent une fonctionnalité spécialisée dans un composant personnalisé. Certains ont transformé leurs composants en produits, et d'autres les publient en libre accès sur la plate-forme Talend Exchange. Si un composant n'est pas disponible dans la palette Talend, cherchez sur cette plate-forme. Un compte Talend Forge est nécessaire, mais vous en avez probablement déjà créé un.

Pour commencer, assurez-vous que le répertoire où les composants seront stockés est bien configuré. Depuis le menu Preferences (Préférences), choisissez un dossier commun que tous les développeurs peuvent utiliser. Cliquez sur Apply (Appliquer), puis sur OK.

Cliquez sur le lien Exchange dans la barre de menu qui permet de sélectionner et d'installer des composants. Lors de la première utilisation, cochez la case Always run in Background (Toujours exécuter en arrière-plan) et cliquez sur le bouton Run in Background (Exécuter en arrière-plan), car le chargement de la liste complète des objets disponibles prend du temps. Depuis cette liste, vous pouvez afficher ou télécharger les objets qui vous intéressent en cliquant sur View/Download (Afficher/Télécharger). Une fois le composant téléchargé, cliquez sur Downloaded Extensions (Extensions téléchargées) pour l'installer et pouvoir l'utiliser dans Studio. Le composant est alors affiché comme Installed (Installé) et disponible depuis la palette.

Il est parfois difficile de localiser un composant installé et ses fichiers associés. Vous devez le rechercher à deux endroits :

{talend}/studio/plugins/org.talend.designer.components.exchange{v}{talend}/studio/plugins/org.talend.designer.components.localprovider{v}

Si vous souhaitez créer votre propre composant personnalisé, passez à la perspective Component Designer (Designer de composants) dans Studio. La plupart des composants personnalisés utilisent JavaJet, l'extension de fichier permettant d'encapsuler du code Java pour l'IDE Eclipse. Un tutoriel Création d'un composant personnalisé est disponible pour les débutants. Bien qu'il date de 2013, il présente efficacement les bases du sujet. Des tutoriels de tierces parties sont également disponibles (certains sont d'ailleurs mentionnés dans le tutoriel). En voici un assez bien fait : Talend by Example: Custom Components. Vous pouvez également faire une recherche dans Google pour trouver plus d'informations sur la création de composants personnalisés.

API JobScript

En général, nous utilisons le Designer pour créer nos jobs Talend, et le Designer génère ensuite le code Java sous-jacent. Vous êtes vous déjà demandé si un Job Talend pouvait être généré automatiquement ? Et bien c'est possible ! Ouvrez le job de votre choix. Trois onglets sont disponibles en bas de la toile : DESIGNER, CODE et JOBSCRIPT. Intéressant. Vous avez probablement déjà cliqué sur l'onglet CODE pour inspecter le code Java généré. Mais avez-vous déjà cliqué sur l'onglet JOBSCRIPT ? Si oui, avez-vous compris ce qui s'affichait ? Je parie que la plupart d'entre vous n'ont pas réalisé de quoi il s'agissait. Cet onglet affiche le script qui représente la conception de job. Regardez plus attentivement la prochaine fois. Je suis sûr que vous reconnaîtrez certains éléments de votre conception de jobs.

Et alors, quelle est l'utilité de cet onglet ? Laissez-moi vous expliquer. Supposons que vous créez et conservez quelque part des métadonnées relatives à votre conception de job, et que vous les exécutez dans un moteur de traitement (que vous créez). Vous générez ainsi un JobScript correctement formaté, en ajustant peut-être les éléments clés pour créer plusieurs permutations du job. Voilà qui est vraiment intéressant !

Dans le Référentiel de projet, sous CODE>ROUTINES, recherchez le dossier Job Scripts. Créez un JobScript (j'ai appelé le mien test_JobScript). Ouvrez n'importe quel job et copiez le contenu de l'onglet JobScript, puis collez ce contenu dans le fichier JobScript et enregistrez. Faites un clic droit sur le JobScript et choisissez Generate Job (Générer le job). Un nouveau job s'affiche dans le dossier Job Designs (Jobs). Imaginez tout ce que vous pouvez faire désormais ! Nice!

Conclusion

Ouf ! Je crois que nous arrivons au bout de cette thématique. Bien sûr, il existe d'autres bonnes pratiques en matière de création et de mise à jour des jobs Talend. Elles pourront être discutées de manière plus large au sein de notre communauté. Je pense pour l'instant que ces 32 bonnes pratiques offrent assez d'éléments solides pour concevoir des projets programmés pour réussir avec Talend.

Dans le prochain article de cette série, nous changerons d'approche et verrons comment appliquer toutes ces bonnes pratiques à un cas d'usage classique. Technologie appliquée, méthodologies solides et solutions efficaces, voilà l'essentiel des bonnes pratiques et modèles de conception de jobs. Merci !

Prêt à faire vos premiers pas avec Talend ?