La Duck Conf 2024 - Compte rendu du talk de Borémi Toch et Grégoire Decavel - Pourquoi le best of des services managés ne vous sauvera pas (complètement)

“Les services managés, ça va vous aider mais probablement pas vous sauver.”

- Père Castor

Une photo de Borémi Toch et Greg Decavel

Lors de la Duck Conf 2024, Borémi Toch et Greg Decavel ont pris les rôles de Père Castor et Castor Junior pour nous conter l’histoire d’un produit autour duquel s’articulent des services managés. Ce produit est accompagné d’une promesse de bonheur: redonner le sourire aux utilisateurs finaux en début de journée. Cette promesse sera-t-elle tenue ? Je vais à mon tour vous raconter cette histoire.

La situation initiale : redonner le sourire aux utilisateurs en début de journée

L’histoire commence avec une entreprise qui promet aux utilisateurs de transports en commun de leur redonner le sourire le matin. Pour se faire, elle souhaite créer une application mobile de rechargement de pass de transport en commun. Quelle idée incroyable ! Les bornes sont généralement prisées et on perd toujours du temps à devoir recharger son pass. On se demande bien ce qui pourrait mal se passer…

Une organisation

Au cours de notre histoire, on va retrouver 3 acteurs principaux:

  • Un utilisateur final, celui à qui est destiné l’application mobile
  • Une équipe produit, celle qui est chargée de créer la logique métier et le cœur de l’application mobile
  • Une équipe OPS… Ou DevOps ? Des Plateform Engineering ? En tout cas, une équipe qui mettra à disposition de l’équipe produit des services managés

Des contraintes

L’application fait l’objet d’un projet, donc l’équipe produit doit respecter certaines contraintes temporelles et de construction:

  • Elle doit construire le SI from scratch et s'interfacer avec des partenaires externes
  • La première mise en service du produit doit s’effectuer dans 1 an

Et puisqu’une architecture soutient l’application, des contraintes techniques d’architecture doivent aussi être respectées:

  • Conformité
  • Disponibilité
  • Sécurité
  • Performance
  • Traçabilité
  • Et bien d’autres !

Ces contraintes sont communément appelées Non Functional Requirements (NFR), ou besoins non fonctionnels. Nous verrons plus tard pourquoi il est préférable de les appeler caractéristiques d’architecture.

Une architecture

Schéma d'architecture global du système avec: à gauche l'utilisateur final, au centre l'application mobile, suivie d'un WAF, suivi d'une API d'achat de pass, suivie d'une base de données, à droite une flèche qui pointe de l'API d'achat de pass à un service externe de paiement

Du point de vue de l’utilisateur final, il n’a qu’à utiliser son smartphone pour recharger son pass de transport. Mais que se cache-t-il derrière ?

Au cœur du système, l’équipe produit met en place l’application mobile et le backoffice qui gère toute la logique métier. Derrière ce backoffice, on retrouve une API d’achat de pass. Et qui dit “achat” dit “paiement”. Puisque l’équipe produit n’est pas experte en paiement, l’équipe OPS lui expose un service de paiement externe qui challengera et validera l’authenticité des transactions des utilisateurs.

L’équipe OPS met aussi en place un Web Application Firewall (WAF), entre l’application mobile et l’API afin de filtrer les appels malveillants, et une base de données pour que l’équipe produit puisse persister les données.

Enfin, pour des raisons de performances, le nombre des serveurs de l’application est augmenté, le nombre de WAF aussi, et les bases de données sont répliquées.

Schéma d'architecture global du système avec: à gauche l'utilisateur final; au centre l'application mobile, suivie de plusieurs couches de WAF, suivis de plusieurs couches d'API d'achat de pass, suivie d'une base de données, suivie de replicas de cette base; à droite une flèche qui pointe des couches d'API d'achat de pass à un service externe de paiement

“C’est la beauté des services managés. Quelques lignes de conf, et pouf, tu disposes de WAF, de bases de données hautement résilientes, scalables, performantes, à faible latence… Formidable. [...] Une archi et une orga c'est bien, mais du coup la [vraie] question derrière c'est est-ce que ça répond à la promesse qu'on a fait à nos utilisateurs.”

- Castor Junior

L’élément déclencheur : un temps de réponse trop lent

Après avoir construit l’application avec de super services managés ultra performants, il était temps de la mettre en service ! Dans un premier temps, l’accès au produit est d’abord réservé à une sous population d’utilisateurs.

La première mise en service du produit

L’utilisateur clique sur son application mobile pour recharger son pass. Et ensuite ?

Cet appel passe par les couches de sécurité avant d’atteindre l’API, puis des informations sont persistées dans la base de données via une connexion jdbc, et enfin le backoffice sollicite le service de paiement. Sauf que…

“Le service de paiement externe avait oublié de prendre son café. Il répond lentement, très lentement.”

- Castor Junior

Schéma d'architecture présentant les appels suivants:
application mobile -> WAF
WAF -> API d'achat
API d'achat -> base de donnée
API d'achat -> image de tortue âgée tenant une canne
image de tortue âgée tenant une canne -> service de paiement

Un timeout de 5 secondes côté front de l’application mobile a été mis en place car il est supposé qu’au-delà de cette limite, l'utilisateur risque d'être frustré et donc d’abandonner l’utilisation du service. Donc au bout de 5 secondes, l’utilisateur re-clique. Tous les appels sont doublés. Mais que se passe-t-il avec une centaine d’utilisateurs frustrés ? Ils cliquent tous, encore.

Le nombre de connexions jdbc étant limité, les requêtes s’empilent plus vite qu’elles ne sont dépilées. Niveau architecture, on a ceci:

Schéma d'architecture présentant les appels de l'application mobile au service de paiement, comme précédemment. Mais avec plusieurs flèches au lieu d'une, et une image d'explosion au niveau des appels de l'API d'achat à la base de données.

Malheureusement, la surcharge de la base de données provoquée par la lenteur de réponse du service de paiement empêche les utilisateurs de recharger leur pass. La promesse de bonheur n’est pas tenue…

Mais ce n’est pas la fin de l’histoire! Le principe de bout en bout allait sauver l’équipe produit.

Les péripéties : le principe de bout-en-bout à la rescousse

Le principe de bout en bout

Le principe de bout-en-bout est un principe élaboré en 1984 par J. H. Slatzer, D. P. Reed et D. D. Clark, chercheurs de l’institut de recherche Computer Science & Artificial Intelligence Laboratory du M.I.T.

Ce principe dit que

“les caractéristiques d’architectures nécessitent de considérer l’ensemble du système de bout en bout. Les sous-systèmes ne peuvent apporter au mieux que des optimisations de performances.”

- Père Castor

Illustrons ce principe avec l’étanchéité de votre salle de bain. Même si vous faites appel au meilleur des plombiers, qui vous garantit l’étanchéité parfaite de votre plomberie, si vous laissez l’eau du robinet couler, votre salle de bain finira inondée.

Dans le cas de notre équipe produit, c’est une latence d’un des sous-systèmes (le service de paiement externe) qui a rendu indisponible l’ensemble du système.

“Et ça, je peux vous garantir que nos services managés les plus performants, résilients, du monde, ils ont pu rien faire face à ça.”

- Castor Junior

Finalement, il faut retenir que même si, individuellement, tous nos services managés sont ultra performants, cela ne peut pas garantir le bon fonctionnement global du système.

Comment appliquer le principe de bout en bout

Pour appliquer le principe de bout-en-bout, assumer vos dépendances. Pour ça, on peut visualiser 3 étapes comme une boucle d’apprentissage à répéter:

1. Mesurer l'expérience des utilisateurs même en cas de dégradation d’un composant. Pour ça, utilisez des métriques. Il faut essayer d’obtenir des mesures objectives afin de pouvoir réagir en conséquence aux situations réelles.

2. Articuler les responsabilités entre les parties prenantes. Qui réagit en cas de panne ? Qui prévient qui ? Qui fait quoi ? Ce n’est pas parce que vous faites appel à des services managés que ceux-ci sont complètement responsables de votre système.

3. Tester le système dans son ensemble pour s’assurer qu’il fonctionne correctement.

Il est important de répéter ces différentes étapes afin de faire émerger des métriques représentatives d’un cas d’utilisation réel du produit. Répondre aux contraintes des NFR de votre produit demande du temps et des moyens. Le processus étant long et fastidieux, vous ne pouvez pas laisser une unique équipe en être entièrement responsable. De plus, si vous ne vous souciez pas de ces NFR, une partie des utilisateurs du produit se retrouvera dans un mode dégradé. Et 1% de un million d’utilisateurs, c’est beaucoup…

“Les NFR, c'est pas fonctionnel mais ça fait malgré tout partie intégrante du produit, traitez le en tant que tel.”

- Castor Junior

“C'est une raison pour lesquelles on aime pas cette expression de NFR, ou besoins non fonctionnels, parce que du coup, comme c'est pas fonctionnel c'est [souvent considéré comme] secondaire, ça va dans le fond du backlog quand y aura le temps. Alors qu'en fait c’est hyper important pour qu'on gagne en résilience.”

- Père Castor

Le dénouement : le passage au 20h

Cette fois-ci, les équipes choisissent de tester le produit en appliquant le principe de bout-en-bout avec des utilisateurs de tests, au lieu de passer directement à une deuxième mise en service.

Plus particulièrement, l’équipe se prépare à un passage au 20h, et donc à une forte population d’utilisateurs au même moment. Pour se préparer à cette forte affluence, l’équipe produit choisit de mettre en place une salle d’attente pour que le système puisse accueillir tout le monde. Cette salle d’attente est exposée par l’équipe OPS, et comme les autres services managés déjà utilisés, elle aussi est scalable, ultra performante, super résiliente, à faible latence, etc.

Verdict ? Heureusement que c’était qu’un test !

Les apprentissages de l’équipe produit grâce au principe de bout-en-bout

Tout d’abord, l’équipe produit pu identifier des problèmes liés à la salle d’attente en mesurant l’expérience des utilisateurs finaux. Certains utilisateurs étaient mis en salle d’attente même quand personne n’était en train d’utiliser le produit, d’autres devaient attendre plus longtemps que des personnes ayant demandé l’accès à l’application après eux, le temps d’attente était trop long, la page était moche… Il ne fallait pas uniquement utiliser le service mais aussi se concentrer sur les modalités de rentrée dans la salle d'attente pour offrir une expérience satisfaisante aux utilisateurs finaux.

L’équipe produit étant elle-même utilisatrice des services managés exposés par l’équipe OPS, il était aussi nécessaire de mesurer son expérience sur ces services car elle n’en était pas forcément une experte. Donc, elles ont décidé de prendre du temps pour faire monter en compétence l’équipe produit sur les nouveaux services.

D’ailleurs, les équipes produit et OPS s’attendaient mutuellement pour configurer la salle d’attente. Comme elles s’en sont rendu compte, elles ont défini clairement les rôles de chaque équipe au sein du système. Ainsi, elles se sont évitées de mauvaises communications pour la suite.

Enfin, les tous premiers tests étaient assez simples, mais en continuant de tester et d’itérer sur la boucle d’apprentissage, elles ont enrichi et amélioré leurs tests et leurs jeux de données de tests. Notamment, les équipes se sont rapprochées au maximum de la réalité pour mieux anticiper les cas réels en utilisant les métriques de leur environnement de production.

Grâce à ces itérations sur la boucle d’apprentissage, les équipes étaient prêtes à ne pas reproduire leurs erreurs, et à affronter le 20h.

La situation finale : une histoire qui finit bien

Il aura suffit aux équipes d’appliquer le principe de bout-en-bout pour que la deuxième mise en service soit un succès et que la promesse de bonheur soit tenue !

Que retenir de l’histoire ?

Quand vous concevez des systèmes, gardez en tête le principe de bout-en-bout et assumez vous dépendances:

Diagramme de la boucle d'apprentissage pour assumer ses dépendances. Cette boucle est constituée des 3 étapes proposées (mesurer l'expérience de nos utilisateur, articuler les responsabilité entre les parties prenantes du système, tester le fonctionnement global en modes nominal et dégradé), reliées entre elles par des flèches.

Quand on fait évoluer les pratiques des équipes, ça fait évoluer l’architecture aussi !

- Castor Junior

Lectures recommandées :