par Guillaume
11 Septembre 2014 Wizacha Algolia Deploiement Anecdote
C’est bien connu, on ne déploit jamais un vendredi! C’est vrai, imaginez que ça se passe mal, ou qu’il y ai un ennui de dernière minute. Ceci étant dit…
Pour les besoins de cet article, voici une description partielle de notre stack. Il y aura certainement un article plus complet un jour pour décrire toute notre architecture.
Notre marketplace tourne sous un CsCart beaucoup modifié. A chaque déploiement, nous lançons, via un template CloudFormation et un ensemble de scripts bash :
L’objectif principal de ce sprint était l’intégration d’un moteur de recherche pour pallier le manque de glamour de la recherche de CsCart.
Nous avons envisagé un temps de gérer une base de données NoSQL dédiée aux recherches. Finalement suite à une discussion avec la maîtrise d’ouvrage, tout le monde était d’accord pour utiliser une solution «toute prête» pour nous faire gagner de la qualité, et du temps (et donc de l’argent).
Nous avons retenu Algolia.
La mise a jour des données dans algolia sera faite de manière asynchrone grâce aux files de messages. Ça permet de garantir que les données seront toujours à peu près justes même si on a une panne réseau temporaire. Ça permet aussi de ne pas se poser la question de ce qu’il faut faire lorsqu’un marchand veut mettre à jour un produit et qu’Algolia n’est pas disponible. Le message restera juste un peu plus longtemps dans la file. (ALERTE SPOILER ça va se révéler une excellente décision)
De plus, CsCart ne vérifiant pas si un produit est modifié lors d’une mise à jour avant de le déclarer mis à jour, nous avons mis en place un système qui permet de savoir si un produit a réellement été modifié ou non. Tout ça dans le but de ne pas renvoyer des données à algolia si on n’en a pas besoin. Plusieurs dizaines de milliers de produits (à l’heure où j’écris ces lignes) étant mis à jour via CSV chaque nuit, il serait rapidement coûteux de tout mettre à jour systématiquement dans algolia.
Algolia garantissant des temps de réponse rapides (<14ms), nous avons décidé d’implémenter la recherche entièrement côté javascript. La documentation d’algolia est bien faite et vient avec des exemples. De toutes façons que la requête à algolia soit faite par le navigateur ou par nos serveurs, ça reste toujours une requête vers algolia. Autant décharger au maximum notre infrastructure, surtout lorsque ce n’est pas plus cher.
Nous devions donc tester la fusion de la branche algolia avec la branche principale le vendredi après-midi, lancer les tests unitaires, déployer trois heures avant de finir la journée, s’assurer que tout marche et rentrer chez nous, remplis du sentiment du devoir accompli.
Tiens, dans ce cas là le produit n’est pas mis à jour !
Tiens, ici CsCart fait une mise à jour directement dans la base de données, du coup, notre hook n’est pas utilisé !
Tiens, les tests unitaires ne marchent plus !
Quelqu’un a donné les droits sur la file SQS pour la prod ?
Finalement, la branche prête, il est 17 heures. On est vendredi, nous sommes raisonnables, le déploiement est reporté.
Je bulle gentiment sur mon pc.
À ce moment là, sentant arriver la suite, je lance ma plus belle console. Petit coup d’historique, premier tunnel SSH. Petit coup d’historique, deuxième tunnel SSH. Je suis chez moi comme au boulot.
(Oui, en début de soirée, je ne suis pas forcement inspiré…)
Petites vérification sur le déroulement des tests de 17h, test rapide pour voir si on peut partager nos écrans. Echec. Tant pis.
C’est parti mon kiki.
(oui, il est purement physique)
(note personnelle : j’aime les notifications hipchat de jenkins)
Pendant le déploiement on s’est dit qu’initialiser tout l’index, même si on met en queue les appels à algolia, pourrait prendre du temps. Pour être sûr de ne pas taper un timeout sur le back-office, on décide de lancer l’init par ligne de commande.
Pour ne pas avoir à me connecter directement sur la machine, et parce qu’on risque d’avoir à le refaire dans le futur, j’écris rapidement un job jenkins qui fait cela.
Branle-bas de combat Rapide coup d’oeil sur les logs, rapide coup d’oeil sur AWS. Une des instances EC2 a été mise en instable par CloudFormation. Il n’y a pas de raison pour que ça vienne de nous, je relance la tâche. (Pour les plus attentifs, j’ai volontairement retiré la notification de succès de la première tâche et le lancement de celle-là.)
À ce moment, je ne peux m’empêcher de me demander s’il n’existe pas un dieu de l’informatique et si ce n’est pas sa façon de me dire que «NON, ON NE DÉPLOIE PAS UN VENDREDI À 21H !!!!!» (oui, cinq points d’exclamations)
Je lance l’initialisation d’algolia.
Donc en fait, j’avais bien fait la mise à jour du fichier de config pour le back en précisant les nouvelles queues, mais je n’avais pas fait la mise à jour dans la configuration des workers. On avait des résultats en front car on a une couche d’abstraction sur les recherches qui permet, si algolia n’est pas disponible, ou pas configuré (comme sur les postes de développement par exemple) d’avoir des résultats via des recherches SQL.
DEPLOY_Front_and_API
Enfin dans une vraie position de travail !
La tâche de déploiement n’est pas encore finie car elle se déclare finie une fois que les DNS sont à jour. Cependant nos workers commencent le boulot dès que la machine est lancée.
Explication :
Pour que l’affichage de la requete puisse être traité exclusivement entre le navigateur et algolia, il faut
bien à un moment stocker chez algolia le bout d’HTML qui sera rendu dans la page de recherche.
On s’est rendu compte que les url des images sont en http://
au lieu de https://
Du coup, les navigateurs
font remarquer à juste titre qu’on a un contenu non sécurisé sur une page qu’on voudrait sécurisée. Du coup,
adieu joli cadenas vert.
Les workers ne répondent pas à des requêtes http, mais traitent des messages. Du coup, on ne s’est jamais posé la question si les workers se considèrent en http ou https. De plus, CsCart ( de manière blameless, mais c’est quand même un peu de sa faute) fait reposer un certain nombre de fonctions centrales (comme la génération des urls) sur des constantes définies à l’initialisation. Conséquence immédiate, c’est très dur de faire de l’injection de dépendances. En plus c’est un appel de fonction planqué dans un template.
Bref, on a laissé passer un bug. Pour le coup, il est un petit peu gênant, mais les navigateurs sont heureux dès qu’on retourne sur les pages produits, donc ça ne mérite pas un rollback.
Note pour la prochaine fois : Envisager un live-tweet
Papotage avec le directeur technique sur les prochaines tâches à traiter, sur les outils, etc.
Du coup, je me jette sur SQS pour voir ce que font nos messages. Globalement, ils stagnent. Au moment où je commence à
taper la commande SSH pour me connecter aux workers, Benoit confirme ce qu’il craignait : «Too many requests»
. On a tapé
le quota sur la machine. Algolia, conformément à notre configuration, nous interdit de nous mettre à jour.
La recherche est pertinente, dynamique, rapide.
Mission accomplie
Le déploiement devrait être plus résistant aux échecs, re-essayer en fonction de l’erreur rencontrée.
Il faut mettre de la qualité dans jenkins. Si quelqu’un fait une modification dans un fichier pour remplacer un
$count = $count + 1
par un $count++
deux autres personnes vont lire la ligne et l’approuver. Par contre, si quelqu’un
supprime la moitié des fichiers de config ou décide de rajouter des étapes au build, personne ne va aller vérifier.
Les déploiements sont longs. Même une fois qu’on a passé les tests, il faut au moins un quart d’heure pour déployer une pile complète (front, back, api, workers). Ce n’est pas dramatique vu notre taille actuelle et parce qu’on fait en sorte d’être rétro-compatibles pour que plusieurs versions puissent se chevaucher. Cependant, ça va finir par devenir gênant.
Je suis très content qu’on ait enfin un moteur de recherche performant. On a tous passé du temps sur l’intégration d’algolia et ce premier résultat est plus que probant.
Have fun with Wizacha