author
La conférence QCon de Londres a été l’occasion pour les équipes du journal “The Guardian” de proposer des retours d’expériences extrêmement enrichissants sur l’architecture de leur site web et l’organisation de leurs équipes de développement. Michael Bruton-Spall, advocate pour le Guardian, a présenté le second jour de la conférence la session: Architecting for Failing.
Le pitch de la session est le suivant: “Your systems are going to fail, it might not be today, it might not be tomorrow, but sometime soon, probably at 2am, your systems are going to fail in new and exiting ways”.
Ce principe a été abordé au cours de plusieurs sessions et fait parti des sujets chauds cette année. La question n’est pas de savoir si votre système tombera, mais plutôt comment vous réagirez lorsque cela arrivera.
Avec la complexité croissante des systèmes informatiques et l’avènement du cloud, les causes de plantage deviennent plus variées et plus nombreuses, et vous ne maîtrisez plus forcement la chaîne d’exploitation de bout en bout. Il est donc nécessaire de monitorer vos systèmes, et d’être préparé à réagir lorsque les choses tournent mal.
Historiquement, le site web du journal The Guardian avait une architecture monolithique. Avec une base de code devenue difficilement maintenable, les équipes ont décidé de revoir le design de leur application et de passer à une architecture à base de micros applications. Le principe est de construire les pages web du site à partir d’un template qui sera complété par l’inclusion de morceaux de code générés par des applications indépendantes. L’idée peut être comparée aux “Servers Side Includes” de l’époque.
Aujourd’hui, ce concept prend un sens nouveau puisqu’il permet de décomposer une application monolithique en de multiples applications indépendantes les unes des autres. Les implications de ce changement sont une maintenabilité bouleversée puisqu’il s’agit de maintenir des multiples applications ayant une complexité bien plus faible et une base de code unitaire réduite. Il devient ainsi plus simple d’appliquer un changement dans une seule des applications et de ne mettre en production qu’une partie de l’ensemble applicatif. Il n’est plus nécessaire d’attendre une release globale pour mettre en production une nouvelle fonctionnalité.
Cette diversification des applications a toutefois un coût puisqu’il est nécessaire de fournir un support et une maintenance pour chacune d’elles. Afin de simplifier les choses à ce niveau, les équipes de développement ont décidé que chaque nouvelle micro-application serait basée sur des technologies tournant sur la JVM.
L’architecture étant basée sur HTTP, il est possible de mettre en cache les données générées par les différentes micro-applications, et de gérer finement les état des différents caches utilisés. Il est ainsi possible de gérer simplement les pages en erreur au niveau du cache, et de ne pas écraser des données de cache valides par des données en erreurs (“stale-if-error” géré par Varnish).
L’architecture à base de micros-applications permet également de tester, releaser, déployer, et gérer un cycle de vie totalement différent pour chacune des applications. Cela permet de simplifier de façon drastique la maintenance de l’application et de faciliter les évolutions. Ce changement d’architecture a toutefois impliqué la mise en place d’un cache systématique afin de limiter des coûts de latence élevés.
Rétrospectivement, le choix d’éclater une application monolithique en de multiples applications indépendantes pouvait paraître risqué puisque cette refonte nécessitait une réécriture en profondeur des applications ainsi qu’une complexification importante de l’architecture, mais ce choix fut vraisemblablement le bon puisque ce changement a permis à l’équipe d’améliorer de façon drastique la maintenabilité de l’application et raccourcir les délais de livraison de nouvelles fonctionnalités.
Par la suite, Michael explique que les équipes ont prévu dans le système différents mécanismes permettant de gérer les imprévus. Les équipes ont ainsi mis en place un mode d’urgence permettant de gérer les pics de traffic: les pages dynamiques étant coûteuses en CPU ainsi qu’en mémoire, il est nécessaire de mettre en place des mécanismes d’urgence permettant de désactiver les traitements coûteux et de privilégier la vitesse. Par ailleurs, les caches de leurs applicatifs n’expirent pas en fonction du temps, mais sur une base de critères variés permettant d’éviter la regénération de contenus lors de pics d’affluence.
Michael explique qu’il est nécessaire de tout cacher, vraiment tout. Les caches in-memory des micros-applications ne sont pas suffisants dans certaines situations: il est nécessaire de cacher des pages entières afin de répondre plus rapidement. Les pages générées sont stockées sur disque et servies en tant que fichiers statiques. Ceci permet de servir plus de 1000 pages par secondes par serveur. Ce mécanisme de mise en cache de pages complètes a pour avantage de ne pas affecter les micros-applications par design.
Le monitoring applicatif est également un aspect essentiel, car il aide à trouver l’origine des problèmes. Il permet de savoir ce qui n’a pas été, quand un problème est survenu, et quel changement a déclenché le problème.
L’aggregation de statistiques dans cette architecture est faite à différents niveaux, et toutes les données monitorables le sont que ce soit des informations de CPU ou bien des informations provenant des micros-applications. Des switchs automatiques permettent d’activer / désactiver des valves, de passer en mode urgence, ou bien de gérer le cas d’une base de données inaccessible. Les valeurs d’activation des switchs correspondent à des valeurs plancher telles que le temps de réponse. Les tendances de ces switchs sont mesurées via leurs outils de monitoring et peuvent être analysées à tout moment.
Michael insiste sur l’importance d’avoir une plateforme applicative “facilement” monitorable. La surveillance des logs doit en être un élément central du système de monitoring. Les logs doivent être parsables, datés, et renseigner sur le code affecté. Enfin, la maîtrise d’outils Unix tels que ‘grep’, ‘cut’, ‘uniq’, ‘sort’, ‘sed’, ou bien encore ‘awk’ doit faire partie de la boîte à outils de chaque développeurs afin de faciliter l’analyse de logs applicatifs.
En fin de session, Michael explique qu’il existe des cas de défaillance prédictibles (Disque dur Fill, CPU à 100%, …), tout comme des cas de défaillance non prédictibles (MTBF, MTBR). Si vous être en mesure d’anticiper ces défaillances du système, vous serez en mesure de récupérer plus rapidement et d’amoindrir l’impact sur vos utilisateurs. La Keynote du dernier jour de la conférence nous confirme d’ailleurs qu’il préférable privilégier le Mean Time To Recovery plutôt que le MTBR. Michael rappelle également qu’il ne faut jamais dépendre trop fortement de services ‘third parties’, car ils failliront toujours au moment le pire et laisseront vos équipes seules face à leurs problèmes. Michael conclut la session sur l’importance d’architecturer les applications de façon à les rendre résiliantes face à d’éventuelles défaillances de composants ou dépendances dont vous n’avez pas toujours la maîtrise complète.
Liens utiles:
- Slides de la présentation: Architecting for failure at the Guardian.co.uk