BI) et des particuliers (open data).
La mise en place de la plateforme débute par l’alimentation en données du DWH. Quelques fournisseurs se sont connectés sur la plateforme pour y déposer leurs données.
Suite au succès de l’intégration des premiers fournisseurs/flux de données, d’autres émettent le souhait de venir déposer leurs données sur la plateforme de données. Afin de permettre ces nouvelles arrivées, un bilan est apparu nécessaire. Trois constats sont dressés .
Un des premiers fournisseurs du DWH a, au bout d’un certain temps, mis à jour le schéma de ses JSON. Cet évènement a entraîné une régression dans la lecture des fichiers car le composant Intégration n’était plus en mesure de lire ces nouveaux schémas. Cette régression a été découverte grâce à une alerte automatique envoyée lors de l’échec d’un batch. Le rollback a été long parce qu’il a nécessité de nombreux échanges entre équipes. Le fournisseur de données a dû déployer une ancienne version de son application pour revenir au schéma JSON supporté par Intégration.
Le schéma des JSON mis à disposition dans la queue, doit être le même que le schéma des JSON attendu par le composant Intégration. Cette obligation de synchronisation est contraignante et provoque une perte de souplesse et d’autonomie pour les équipes lors des mises en production. Ce problème fait écho au premier constat.
Aujourd’hui, il n’y a aucun endroit qui référence les schémas existants. Leurs définitions n’ont pas été centralisées,ni mises à disposition des équipes productrices et consommatrices des données. Cela rouvre régulièrement des échanges sur ce qui a déjà été acté.
Suite à ces constats, il apparaît essentiel de résoudre ces différents problèmes pour être en mesure d’accueillir plus d’utilisateurs sur le DWH et garantir une bonne intégration des données.
Les problèmes rencontrés lors de l’état des lieux mettent en évidence des besoins :
Cependant, il existe également des contraintes :
Ces exigences sont essentielles pour éviter une augmentation importante de la charge de travail et un ralentissement du développement du programme.
Les besoins mis en évidence peuvent être abordés avec une multitude de solutions. Ici sont détaillées uniquement les réponses mises en place par l’équipe data.
Afin d’éviter des régressions et de longs échanges entre l’équipe data et les fournisseurs, en cas d’erreur sur le schéma des fichiers déposés dans la queue, il a été décidé d'implémenter un schéma registry inspiré de celui de Kafka. Il a été décidé de créer le schéma registry plutôt que d'utiliser un produit clef en main pour ne pas avoir besoin de débourser plus d'argent que le coût de la mise en place et de la maintenance.
Le schéma registry se traduit ici par la mise à disposition, via une API, des schémas des json acceptés par le composant Intégration. Ces derniers sont générés à la volée à partir des pojos (plain old Java object) dans le code d’intégration. Les schémas sont donc toujours à jour sur tous les environnements. Les objets Java sont la source de vérité pour le maintien des contrats d’interface.
Une nouvelle étape permet aux fournisseurs de venir contrôler le fichier qu’ils s’apprêtent à envoyer.
Un exemple d’implémentation est disponible sur GitLab.
En contrepartie, cette solution demande des ouvertures de flux supplémentaires pour que les fournisseurs puissent venir requêter l’API d’intégration. De plus, elle nécessite de mettre en place une haute disponibilité pour le composant Intégration qui ne peut plus se permettre des interruptions de service. Son API doit être disponible à tout moment.
Le schéma registry de Kafka se distingue de la solution mise en place.
La différence majeure avec le schéma registry de Kafka est d’abord la possibilité d’utiliser plusieurs formats, notamment Avro, ainsi qu’une large gamme d’outils facilitant les développements. Il est par exemple possible, avec Avro, de ne pas passer les headers dans les fichiers transférés. Ils sont reconstruits à l’aide du schéma registry. Cela permet des transferts de fichiers plus légers.
Au vu de la taille des fichiers (quelques Mo) et du besoin de fraîcheur des données, ces avantages ne sont pas un besoin pour l’équipe data. Il n’est pas envisageable d’utiliser le format Avro, car sa mise en place est coûteuse. Il est donc important de minimiser l'impact sur l’ensemble des parties prenantes.
Le schéma registry de kafka est également plus souple, en effet les fournisseurs peuvent pousser leur propre schéma dedans. Pour reproduire ce comportement, le composant d’intégration devrait s’adapter en fonction des schémas donnés par les fournisseurs. Pour ce faire, il faudrait générer des pojos à partir des schémas.
Ici encore cette fonctionnalité n’est pas un besoin. Elle serait coûteuse en temps pour la mettre en place.
Pour éviter de devoir synchroniser les mises en production des fournisseurs et du composant d’intégration, des contraintes sur l’ évolution des schémas sont nécessaires.
Une des réponses possibles pour ce besoin est de garantir la compatibilité entre les versions de schéma N et N+1. Les principes peuvent être retrouvés dans l’article Zero Downtime Deployment. Dans le cas de compatibilité de schéma json, il s’agit du type de compatibilité backward. Si le producteur veut proposer son schéma, aucun moyen simple n’a été trouvé pour pouvoir l'accepter. C’est donc toujours le consommateur qui sera à l’initiative des évolutions de schéma. Mettre en place la backward compatibility demande quelques ajustements. Il faut, lors d’un changement de version (N+1 -> N+2), que le composant intégration s’assure qu’il ne recevra plus de json avec un schéma en version N. Un des moyens est de monitorer la queue. Pour aider le monitoring, il peut être de bon ton de garantir que l’ordre de lecture des fichiers correspond à leur ordre d’arrivée (FIFO).
Si les mises en production sont moins risquées avec la rétrocompatibilité des schémas, il reste à centraliser et publier les contrats d'interfaces attendues.
Pour partager un point de vérité, facilement entre les équipes, un moyen est de mettre à disposition de la documentation sur le contrat d'interface, au format markdown, sur un gestionnaire de version (ici : Gitlab). Comme pour le schéma registry, les objets Java sont la source de vérité des contrats d’interface. Il suffit d’ajouter une étape dans la CI pour générer le nouveau fichier .md lorsque l’on déploie sur un environnement et le déposer sur le gestionnaire de version. Voici un exemple de documentation :
Dans la documentation peuvent figurer :
Ces solutions permettent de répondre aux besoins identifiés pour un changement d’échelle. Cependant elles ne résolvent pas tout.
Les fichiers de la queue ne sont pas supprimés après avoir été consommés. Ils ont une période de rétention. L’objectif est de pouvoir faire une reprise de données sans demander aux fournisseurs de publier une seconde fois leurs données. Cela vaut dans le cas où la reprise ne concerne pas un historique de données trop profond et/ou les données envoyées ne sont pas corrompues. Cependant, si le schéma d’un flux change plus de deux fois, cette reprise nécessitera des actions manuelles, sera partielle et/ou demandera un code très résilient pour être effectuée.
La mise en application des différents éléments de résolution n’est pas toujours nécessaire. Ils ont été mis en place dans le contexte de cette mission, néanmoins, dans un contexte avec moins de flux et de fournisseurs, il semble possible de s’en passer. Dans ce cas, n’est-il pas urgent de ne rien faire ?