Devenir un service d’indexation et de recherche à la demande au sein de son S.I.
Le passage d’une utilisation à la demande du célèbre moteur de recherche Elasticsearch à une utilisation industrielle, par de nombreux clients diversifiés, au sein d’un même S.I., demande quelques adaptations qui ne sont pas toujours évidentes à imaginer ou à comprendre sans entrer dans des considérations d’architecture, de contrat de service, de sécurité et d’urbanisation.
Pour mieux comprendre les enjeux d’une plateforme de service à la demande et les adaptations nécessaires par rapport à une approche classique, cet article vous propose de faire un état des lieux de deux cas d’usage habituels avant d’en étudier les avantages et inconvénients:
- Indexation et recherche de documents métiers
- Centralisation des logs
Une fois ces avantages et inconvénients connus, il sera alors possible de réfléchir aux moyens à mettre en oeuvre pour conserver une gouvernance sérieuse et efficace de notre S.I malgré une montée en nombre des clients ainsi que des contraintes induites…
Une proposition d’architecture servira à expliciter les adaptations et concessions nécessaires à une utilisation comme plateforme centralisée au sein du S.I
Cas d’utilisation standard
Usages métier
En production, un cluster Elasticsearch utilisé pour indexer ou rechercher des documents métiers est souvent organisé selon le schéma suivant.
Pour chaque application utilisatrice:
- Un pool de connexions HTTPs/TCPs selon utilisation de clients REST/Json ou bien du protocole “Transport” d’Elasticsearch
- Un truststore valide pour initialiser ces connexions sécurisées vers le cluster protégé par SearchGuard, Shield ou X-Pack…
- Du code pour les requêtes de recherche et d’indexation
- Des transactions ou transactions globales[1] pour les indexations et autres écritures de données
- Des paramètres pour indiquer la liste des noeuds Elasticsearch à contacter
- Des paramètres pour indiquer la liste des alias d’index à utiliser pour le métier considéré
- Du code d’initialisation des mappings pour le métier considéré
- Des paramètres pour les identifiants/mot de passe de l’utilisateur applicatif du cluster Elasticsearch si protégé par searchGuard, Shield ou X-Pack…
- Une route réseau ouverte entre le serveur d’application et les noeuds du cluster
Les avantages de cette solution
- Chaque appel est personnalisé et reste à la main complète du client
- Chaque appel peut être considéré comme synchrone puisque le statut de la réponse à l’opération demandée est donné par le cluster lui-même., Ainsi, les opérations d’indexation peuvent s’insérer dans de simples transactions ou bien des transactions globales (ES + DB + fichiers par exemple)
Les désavantages potentiels de cette solution
- Chaque document doit être construit au préalable en json
- Nécessité de connaître l’API Rest/Json ou l’API Java d’Elasticsearch
- Impossible de consolider ou d’enrichir les données automatiquement avant insertion avec:
- Gestion de métadonnées (ex : timestamp de centralisation, champs d’identification de l’application cliente si non prévue par elle,…)
- gestion automatique de la rotation des index si non prévus par l’application
- En cas de panne momentanée ou d’arrêt du cluster pour maintenance, les traitements sont bloqués et :
- soit annulés pour erreur
- soit mis en attente pour nouvelle tentative au prix d’un développement spécifique côté applicatif
- Dépendances vers des librairies de versions potentiellement différentes d’accès à Elasticsearch (couplage fort)
- Le niveau de sécurité, la facilité de monitoring/audit, le niveau des performances peuvent poser problème avec l’augmentation du nombre de clients
Les désavantages d’une augmentation du nombre de clients
- Dispersion et multiplication des paramètres dans les livrables
- Les mappings sont dispersés et liés fortement aux livrables des applications
- Traçabilité des actions de modification sur le cluster difficile (quand, qui, quoi…)
- Maintenance rendue difficile par la disparité des modes d’indexation et des langages d’appel
- Le nombre de clients impacte grandement les performances globales du cluster sans que l’on puisse vérifier facilement la qualité des appels effectués ou répartir autrement les documents et notamment sur des clusters différents en raison des nombreuses adhérences clients…
- Manque de rationalisation des ressources, chaque application pouvant gérer son propre cluster, dans sa propre version, les clusters consommeront machines, mémoire, cpu ou espace disque de manière non optimale …
Usage des brokers et d’Elastic Stack pour centralisation de logs
En production, la suite Elastic Stack est souvent accommodée d’une ou plusieurs instances de brokers.
Voici une architecture habituelle de centralisation des journaux applicatifs
Les brokers comme Kafka, RabbitMQ ou autres sont des composants utilisés de manière assez habituelle dans une infrastructure Elastic Stack de centralisation des logs.
Ces composants, selon leurs paramètres, peuvent amener de nombreux avantages architecturaux:
- Découplage d’exécution entre applications clientes et moteur de recherche
- Multiplexage des messages vers plusieurs destinataires (réplications multi-sites temps réel…)
- Persistance des messages avec parfois possibilité de réémission
- Centralisation des messages à distribuer avec les avantages suivants:
- possibilité de journalisation centralisée
- possibilité de sécuriser les écritures vers Elasticsearch en exposant le seul broker aux clients
Les composants comme Logstash sont sans état et permettent donc une mise à l’échelle horizontale et une consolidation/transformation des logs avant envoi vers le cluster Elasticsearch.
Les avantages de cette solution
- L’envoi des messages est asynchrone, l’application ne s’en occupe plus
- pas de dépendance vers une librairie versionnée d’Elasticsearch puisque les messages sont du texte (couplage lâche)
- mise à l’échelle facilitée
- consolidation des données centralisées (timestamp, qui=topic pour kafka, quoi, …)
- gestion des indexations en mode bulk par défaut avec l’output Rest Elasticsearch
- gestion des rotations d’indices automatiques
- utilisation des templates d’indices pour définir des mappings
- les clients ne connaissent rien de la version des outils de la stack Elastic ou de la répartition de leurs logs sur des clusters différents ce qui permet une malléabilité intéressante
- le système est en “append only” ce qui empêche les destructions de documents accidentelles ou volontaires
- sécurisation facilitée car les noeuds du cluster peuvent n’accepter que les connexions depuis le ou les logstashs dédiés
- sécurisation facilitée comme seuls les logstash doivent posséder les paramètres de connexion au cluster
- Aucune solution de requêtage n’est à développer puisque des solutions génériques de requêtage et de visualisation de logs comme Kibana existent
Les désavantages potentiels de cette solution
- L’envoi des messages est asynchrone ce qui empêche de gérer l’indexation dans une transaction ou transaction globale*
*Transaction globale: Une transaction globale est un mécanisme qui permet à plusieurs routines de programmation, qui peuvent être mises en jeu par un ou plusieurs serveurs, de s’exécuter pour fournir une seule fonctionnalité logique persistante.
Devenir plateforme de recherche et d’indexation à la demande dans tout ça ?!
Comme nous l’avons vu, le mode d’utilisation en mode logs présente beaucoup plus d’avantages que l’utilisation business recherches + indexations métier.
Par ordre d’importance, je dirai que les avantages sont:
- Sécurisation et traçabilité facilitées
- Mise à l’échelle facilitée
- Rationalisation des ressources
- Découplage du code entre application et versions d’Elasticsearch/simplification des déploiements
- Découplage des applications et du déploiement final du ou des clusters Elasticsearch
- Centralisation des configurations
- Possibilités de consolidation centralisée des documents indexés
- Gestion automatique des rotations et templates d’index
- Réduction des compétences nécessaires à propos de la stack Elasticsearch côté applicatif
Or, qu’est-ce qui fait que les documents métiers ne puissent être utilisés avec cette architecture brokers + Elastic Stack ?
En fait, avec l’expérience, on s’aperçoit que les éléments importants qui empêchent l’utilisation de la stack Elastic pour des documents métiers sont les usages nécessitant des activités de type CRUD ( créations, mises à jour et destruction de documents métiers identifiés de manière unique ):
- ils nécessitent une indexation ou destruction pouvant être insérée dans une transaction et donnant un statut de manière “synchrone” pour déterminer la suite du comportement applicatif
- ils nécessitent des requêtes de recherche ou de listage à écrire dans l’application, car des traitements seront attachés à leurs résultats
- ils nécessitent parfois une analyse complexe pour représenter de manière personnalisée les résultats aux utilisateurs
De même,l’expérience aidant, on s’aperçoit également qu’il peut y avoir des usages métiers se rapprochant des logs par leur construction:
- lorsque les documents destinés à construire des métriques orientées métier dites “analytiques” sont visualisables par des outils existants
- lorsque des solutions génériques de requêtage et de visualisation comme Kibana existent
- lorsque l’utilisation des documents métiers est faite par d’autres applications que l’application source des données (Ex: batchs, utilisation/découverte en mode Excel, …)
Exemple de logs métiers exploitables sans CRUD
10/12/2017 INFO Main client=CLIENT-3302202203, action=achat, produit=REF-032203203, totalHT=20€, totalTTC=22€, mode_paiement=CB
Dès lors, nous pouvons dresser un premier bilan sur la mise en place d’un centre de service d’indexation et de recherche au sein de son S.I.:
- Il est difficile d’assurer un niveau de maîtrise suffisant dès que les applications demandent des usages spécialisés et orientés CRUDs.
- Il est utile d’utiliser le mode Broker + Elastic Stack dès que possible pour toute application métier compatible
Proposition d’architecture pour adapter le mode broker + Elastic Satck aux usages du CRUDs
Tout d’abord, nous comprenons assez rapidement que les requêtes d’interrogation métier seront inévitablement effectuées en direct sur le cluster Elasticsearch car elles serviront à générer des comportements applicatifs et/ou des interfaces homme-machines sur mesure.
Cette partie ne peut donc être améliorée…
Par contre, qu’en est-il des indexations / mises à jour ou destructions de documents?
Nous l’avons vu, les principaux problèmes de ce mode d’utilisation sont:
- La perte du mode “synchrone”
- Le mode “append only” par défaut qui empêche les mises à jour ou les destructions de document
- La difficulté à faire passer des objets complexes en mode texte ou en json via un broker puis les désérialiser/transformer dans Logstash
Mais est-ce vraiment une limitation réelle ?
Non.
Heureusement, si la perte du mode synchrone peut être problématique dans certains cas,elle n’est pas rédhibitoire et Logstash est bien capable de parser des objets complexes pour les mettre à jour ou les détruire dans Elasticsearch à la condition que l’application émettrice fournisse quelques informations supplémentaires obligatoires dans le message transmis:
- L’id du document
- Le type du document
- L’action à effectuer
Présentation de la solution d’optimisation avec ses concessions
La solution consiste à faire passer toutes les actions d’écriture CRUD ou non par un Broker puis par la plateforme Elastic Stack. Ceci apporte bien entendu des contraintes qu’il faut alors prendre en compte…
Au niveau des applications
Les documents à traiter (lors d’une création, mise à jour ou destruction) doivent obligatoirement contenir leur identifiant métier ainsi que l’action à effectuer pour que Logstash sache quoi en faire.
Le type d’un document pouvant être déterminé selon sa provenance, voir section logstash pour le mode de récupération de cette information, l’application n’est pas obligée de traiter ce point dès l’émission, c’est le choix du canal d’envoi qui permettra de transmettre l’information obligatoire à Logstash
Attention, pour rappel, l’utilisation d’un broker comme tampon induit les conséquences suivantes :
- Pas de gestion transactionnelle possible puisque l’application cliente n’a plus la main après envoi au broker
- Pas de retour immédiat et typé des éventuelles erreurs lors de l’exécution de l’action souhaitée
Pour limiter ces problématiques sans complexifier outrageusement code et conception, voici quelques exemples de règles de développement de code métier possibles.
Cas de données sensibles pour l’exécution du processus métier
- Stocker temporairement la donnée complète dans une table dédiée et dénormalisée en BDD au cours d’une transaction (A)
Nb: Si documents à forme changeante, stocker un blob
- En cas de commit effectif de la transaction, envoyer le document au broker (Fire and forget)
Dans tous les cas
- Exécuter une vérification de la présence du document dans le moteur de recherche à temps de commit + refresh interval + 1s et purger la donnée temporaire stockée si succès
- Exécuter régulièrement en arrière-plan un batch de synchronisation entre BDD et moteur de recherche pour ajouter les documents manquants. Les données stockées en BDD ( en A ) sont purgées si présentes dans le moteur de recherche
- Les recherches doivent indiquer à l’utilisateur si la table des documents temporaires n’est pas vide depuis un certain temps
- Paramétrer Logstash pour que les erreurs de parsing des documents soient tracées et remontées aux administrateurs ou dans la dead letter queue de Logstash
Cas de données complexes
De manière générale, émettre des documents au format json n’a aucun intérêt si l’on passe par Logstash et non directement par Elasticsearch. En effet, Logstash devra de toute manière parser le json pour pouvoir le manipuler(préemption du CPU Logstash).De plus, le format json prend beaucoup de place avec le rappel des noms des champs pour chaque valeur (Préemption de disque et de bande passante du LAN)…
Aussi, on préfèrera en général émettre au format texte en raccourcissant les dates (epoch time in millis) + UTC et en utilisant un séparateur de champ ‘rare‘ (Ex: ‘|’) pour distinguer les différents champs du document
Mais ceci ne suffit pas s’il est nécessaire de construire des champs complexes avec des sous-objets ou des tableaux de sous-objets.
Ex: Les livres suivants peuvent être difficiles à dénormaliser au format texte avec de simples séparateurs de champs…
{ “titre”: “Livre 1”, “auteurs”: [ { “nom”: “NomAuteur1”, “prenom” : “PrenomAuteur1 }, { “nom”: “NomAuteur2”, “prenom” : “PrenomAuteur2 }] } ou { “titre”: “Livre 3”, “auteurs”: [ “Prenom1 NomAuteur1”, “Prenom2 NomAuteur2” ] }
Le cas des tableaux simples peut être résolu en utilisant des “filtres” Logstash comme:
- Csv à l’aide du champ spécifié par l’option ‘source’ du filtre Csv
- Kv (key value) à l’aide du champ spécifié par l’option ‘source’ du filtre kv
- Split à l’aide du champ spécifié par l’option ‘field’ du filtre Split
Pour les sous-objets ou tableaux de sous-objets, il est recommandé d’utiliser le filtre json capable de récupérer un objet json à partir du texte situé dans le champ spécifié par l’option ‘source’ du filtre.
Ex:
1472800657644|th1|I|Utilisateur 1|Service gestion du panier|{"panier": [{"livre":{"titre":"Angular", "auteurs":[“Daniel Djordjevic”, “William Klein”, “Sébastien Ollivier”]}, {"livre":{"titre":"Qt5", "auteurs":“Tristan Israel”}]|suite du message textuel ...
Au niveau de Logstash
Inputs des brokers
Les inputs des brokers peuvent nous donner des indices sur le type de document à traiter.
Les inputs permettent de récupérer cette information, soit en ayant un input exclusif par type de document, soit en récupérant des données supplémentaires fournies par l’input lui-même:
- topic pour Kafka
- exchange et/ou content-type pour RabbitMQ
- destination pour Jms
- …
Pour le cas de Kafka par exemple l’input peut indiquer le topic du document et positionner en conséquence la valeur de la métadonnée Logstash suivante:
[@metadata][kafka][topic]
Cette donnée pourra être utilisée dans l’output Elasticsearch sans forcément la stocker dans le document.
Output Elasticsearch
La récupération de l’identifiant du document et de l’action à effectuer n’a rien de complexe. Il suffit de récupérer ces valeurs dans le document parsé, puisque les applicatifs les ont fournis, et de les utiliser comme paramètres de l’output Elasticsearch
Pour cela, positionner les paramètres suivants à la valeur adéquate dans l’output Elasticsearch:
- document_id qui permet de transmettre l’identifiant du document cible de l’action
- action qui permet de spécifier l’action index, create, update ou même delete
Rappel: Il est possible d’ajouter une politique de rotation des index via l’option index de l’output Elasticsearch. Ex: ‘monMetier-%{+YYYY.MM.dd}’
Au niveau d’Elasticsearch
De manière habituelle, un template d’index est utilisé par les indexations Logstash.
Comme les documents métiers peuvent être beaucoup plus complexes, il est nécessaire de définir un template d’index explicite pour chaque document, via l’API dédiée, pour y définir un mapping qui réponde spécifiquement aux besoins des recherches applicatives.
Conclusion
Nous avons vu dans cet article tous les avantages qu’offre l’approche de l’indexation à la manière de logs, via la suite Elastic Stack, pour une plateforme de service d’indexation et de recherche à la demande face à des clients multiples et en nombre croissant au sein du S.I.
En résumé:
- Une meilleure rationalisation
- Consolidation des données
- Sécurité
- Simplification de déploiement
L’approche par logs amène bien sûr des avantages et inconvénients qu’il faudra bien expliciter aux clients potentiels de la plateforme. Bien qu’il existera toujours quelques applications qui ne peuvent s’accommoder des contraintes vues ici, la plupart d’entre elles devraient fonctionner dans le mode proposé et ainsi profiter au S.I dans son ensemble.
Pour aller plus loin dans les avantages de la solution me direz-vous ?
Et si les brokers devenaient une sorte d’ESB ?