Aller au contenu
Télécharger
Tous les articles
Guides

Comment nous avons amélioré les performances de Moove de 59 %

La plupart des utilisateurs de Moove sont loin de nos serveurs. Comment nous avons réduit de 59 % le délai de première réponse sans déplacer de serveur.
6 nov. 20269 min de lecture

La distance était notre dépendance la plus lente

La plupart des personnes qui ouvrent la Moove app sont sur des réseaux mobiles au Nigeria et en Indonésie, à des milliers de kilomètres des serveurs qui leur répondent. Ce mois-ci, nous avons changé la manière dont leurs requêtes nous parviennent, et notre délai avant le premier octet (TTFB), c'est-à-dire le temps qui s'écoule entre l'envoi d'une requête par un téléphone et l'arrivée du premier morceau de la réponse, a baissé de 59 %, passant de 0,74 seconde à 0,31 seconde. Nous n'avons déplacé aucun serveur pour y parvenir.

Cet article explique pourquoi la distance nous coûtait plus cher que prévu, ce que nous avons changé, la partie qui s'est révélée plus difficile que le changement lui-même, et ce que nous dirions à une autre équipe sur le point de faire la même chose.

Pourquoi un long trajet devient trois

Les ingénieurs appellent latence le délai entre l'envoi d'un message et son arrivée, et temps d'aller-retour (RTT) le temps nécessaire pour qu'un message atteigne un serveur et que la réponse revienne. De Lagos à nos serveurs, le RTT se situe entre 200 et 300 millisecondes. Pris isolément, c'est tolérable. Le problème, c'est qu'une requête voyage rarement seule.

Avant qu'un téléphone puisse demander quoi que ce soit via une connexion sécurisée, il doit mener à terme deux négociations de connexion (handshakes), ces brefs échanges qui établissent une connexion. Le handshake TCP ouvre la connexion, puis le handshake TLS convient des clés de chiffrement qui la gardent privée. Chacun coûte un aller-retour complet. Ce n'est qu'ensuite que la requête elle-même part, ce qui fait un troisième trajet. À 250 millisecondes le trajet, un utilisateur attend environ trois quarts de seconde avant que nos serveurs n'aient effectué le moindre travail.

Sur les réseaux mobiles, ce coût est payé bien plus souvent qu'on ne l'espère. Les téléphones passent d'une antenne à l'autre, les radios se mettent en veille pour économiser la batterie et les applications sont envoyées en arrière-plan. Chacun de ces événements peut couper la connexion, et la requête suivante doit repartir d'une connexion à froid, c'est-à-dire sans aucun handshake effectué, et payer à nouveau le coût complet de l'établissement. Une connexion à chaud, déjà ouverte et sécurisée, passe directement à la requête.

Nous ne pouvions pas rapprocher Lagos de nos serveurs. Nous pouvions en revanche rapprocher l'établissement de la connexion de Lagos.

Déplacer le handshake, pas les serveurs

Un réseau de diffusion de contenu (CDN) est généralement décrit comme un cache : un ensemble d'emplacements répartis dans le monde qui conservent des copies de fichiers pour les servir depuis un point proche. Nous en avons utilisé un pour une autre raison. Pour notre API, l'interface avec laquelle l'application communique pour tout ce qu'elle fait, la mise en cache est entièrement désactivée. Chaque requête continue de voyager jusqu'à notre origine, le nom que donne le CDN aux serveurs situés derrière lui.

Ce qui change, c'est l'endroit où la connexion démarre. Un téléphone ouvre désormais sa connexion vers l'emplacement périphérique le plus proche, aussi appelé point de présence (PoP) : l'un des sites du CDN répartis dans le monde, souvent à quelques dizaines de millisecondes plutôt que quelques centaines. Le point de présence réalise la terminaison TLS, ce qui signifie que la connexion sécurisée du téléphone s'arrête là. Il réutilise ensuite un ensemble de connexions à chaud vers notre origine, maintenues ouvertes grâce à keep-alive, un réglage qui laisse une connexion ouverte entre les requêtes au lieu de la fermer. Les deux trajets d'établissement coûteux se font sur le court tronçon, et seule la requête elle-même traverse l'océan, sur une connexion déjà chaude.

Trois longs trajets deviennent un long trajet et deux courts. Toute l'idée tient là.

Nous avons volontairement gardé le reste très sobre :

  • Les clients n'ont rien remarqué. L'application et le site web ont conservé les mêmes adresses, donc aucune nouvelle version de l'application n'était nécessaire et personne n'a eu de mise à jour à faire.
  • Le comportement en cas d'échec est resté le même. Les délais d'expiration correspondent à ce qui existait avant, donc tout ce qui échouait auparavant échoue de la même manière. Nous ne voulions aucun nouveau type d'erreur.
  • Le point de présence ferme les connexions inactives en premier. Chaque connexion a un délai d'inactivité, la durée pendant laquelle elle peut rester inutilisée avant d'être fermée. Si nos serveurs fermaient une connexion silencieuse alors que le point de présence la croit encore ouverte, la requête suivante échouerait. En réglant un délai plus court côté point de présence, c'est toujours lui qui abandonne le premier et ouvre une nouvelle connexion.
  • Des protocoles plus récents pour les téléphones. Les téléphones peuvent se connecter en HTTP/3, la dernière version du protocole de requêtes du web. Il repose sur QUIC, qui fond les deux handshakes en un seul aller-retour et gère mieux la perte de paquets, fréquente sur les réseaux mobiles.
  • Aucune région laissée de côté. Les offres moins chères d'un réseau périphérique omettent souvent des emplacements dans les régions du monde mêmes où vivent nos utilisateurs ; nous avons donc choisi une couverture complète.

Ce que nous avons mesuré

Nous avons mesuré depuis Sydney, qui est à peu près aussi loin de nos serveurs que Lagos, en comparant l'ancien chemin au nouveau. Pour chacun, nous avons ouvert cinq connexions à froid neuves, le cas qui compte le plus sur les réseaux mobiles, et pris la médiane, notée aussi p50 : le résultat du milieu, que la moitié des requêtes battent et que l'autre moitié ne battent pas. Le même projet a aussi activé la compression des scripts de notre site web, qui étaient envoyés à leur taille complète. La compression réduit un fichier avant son envoi et le navigateur le décompresse à l'arrivée ; nous avons utilisé Brotli, un format de compression conçu pour le web.

Ce que nous avons mesuréAvantAprèsAmélioration
Handshakes TCP et TLS terminés (p50)490 ms59 ms88 % plus rapide
Délai avant le premier octet (p50)743 ms307 ms59 % plus rapide
Poids des scripts de la page d'accueil1.76 MB560 KB68 % plus léger

Le délai avant le premier octet est l'origine des 59 %. Une connexion qui mettait une demi-seconde à s'établir est désormais prête en moins d'un dixième de seconde, et une première visite sur notre site web télécharge désormais deux tiers de données en moins, sur des connexions où beaucoup de gens paient chaque mégaoctet.

Ces chiffres proviennent d'une seule ville, pas d'un test de référence mondial. Le calcul vaut toutefois aussi pour Lagos et Jakarta, et c'est là que se trouvent nos utilisateurs.

Le plus difficile était de savoir qui appelle

Placer quelque chose devant vos serveurs est facile. Faire continuer à fonctionner vos protections derrière a demandé l'essentiel de l'effort.

Comme la plupart des plateformes de paiement, Moove utilise la limitation de débit, un plafond au nombre de requêtes qu'un appelant donné peut faire sur une période donnée, et ces limites sont indexées sur l'adresse IP de l'appelant, le numéro qui identifie un appareil sur internet. Derrière un réseau périphérique, chaque requête arrive depuis l'adresse d'un emplacement périphérique plutôt que depuis celle de l'utilisateur. Si rien d'autre n'avait changé, tout Lagos aurait partagé un seul budget, et un après-midi chargé aurait commencé à refuser des personnes qui n'avaient rien fait de mal.

La solution repose sur deux idées.

Faire confiance exactement aux couches que l'on a. Un CDN est une sorte de proxy inverse, un serveur placé devant le vôtre qui transmet les requêtes. Chaque proxy ajoute l'adresse d'où il a reçu une requête dans un en-tête standard appelé X-Forwarded-For, de sorte que le véritable appelant se trouve à un nombre fixe d'étapes, ou sauts, en remontant dans cette liste. Se tromper sur ce nombre est un bogue dans les deux sens. Compter trop peu de couches, et chaque utilisateur ressemble à son emplacement périphérique. En compter trop, et l'on se met à faire confiance à une entrée écrite par l'appelant lui-même. Nous avons donc fait de ce nombre une propriété de l'infrastructure plutôt que du code. Il change au même moment que le réseau, et notre service refuse de démarrer si la valeur n'a aucun sens, plutôt que de deviner.

Laisser le point de présence se porter garant de l'appelant, et ne croire que lui. Le point de présence écrit désormais l'adresse du véritable appelant sur chaque requête et écrase tout ce que l'appelant avait envoyé à la place. Nos protections ne croient cette valeur que lorsqu'elles peuvent vérifier que la requête est réellement passée par notre point de présence. Chaque limite qui reposait sur l'adresse réseau repose désormais sur le véritable appelant pour le trafic passant par le point de présence. Nous avons ajouté ces règles à côté des anciennes au lieu de les modifier, si bien que chaque changement du déploiement était un simple ajout que n'importe qui pouvait relire en une fois.

Un bogue repéré avant la mise en production

Les Moove Profiles peuvent vivre sur le domaine propre d'un commerçant. Les requêtes pour ces domaines étaient transmises via notre site web avec le domaine du commerçant attaché, afin que le site sache quel profil afficher.

Le nouveau point de présence placé devant le site web retire ce type d'information des requêtes entrantes, ce qui est tout à fait normal, car un visiteur ne devrait jamais pouvoir la définir. Cela signifiait aussi qu'une fois le site web derrière le point de présence, chaque domaine de commerçant aurait discrètement affiché la page d'accueil de Moove au lieu du profil du commerçant.

Nous l'avons repéré en relecture, nous avons d'abord déplacé le chemin des domaines de commerçants vers sa propre route, et nous avons fait en sorte que notre infrastructure refuse d'appliquer le changement du site web partout où ce déplacement n'avait pas eu lieu. Une erreur qui ne vivait auparavant que dans la tête d'un relecteur est désormais quelque chose que la compilation bloque.

La leçon générale : quand vous ajoutez une couche qui nettoie les entrées, cherchez tout ce qui dépendait des entrées que vous êtes sur le point de nettoyer.

Comment nous avons déployé

Une infrastructure de paiement ne se prête pas au « déployer et voir », donc nous avons d'abord modifié l'environnement de préproduction, puis la production, et quelques choix ont rendu la bascule sans histoire. Nous avons réduit le TTL (durée de vie) de nos enregistrements DNS, l'annuaire d'internet qui transforme un nom comme moove.xyz en adresse de serveur. Le TTL est la durée pendant laquelle le reste d'internet peut garder cette réponse en cache, et nous l'avons fait passer d'une heure à cinq minutes, une heure entière avant que quoi que ce soit ne bouge, de sorte que l'ancienne réponse avait expiré partout et qu'un retour en arrière prendrait effet en quelques minutes. Nous avons conservé les enregistrements d'adresse sous une forme qui pouvait être modifiée sur place, car les supprimer puis les recréer aurait laissé un trou, et un trou est une panne. Chaque étape risquée était un petit changement à part, avec les étapes pour l'annuler écrites dans l'ordre.

Ce que nous dirions à une autre équipe

Si vos utilisateurs sont loin de vos serveurs, un réseau périphérique vaut la peine même s'il ne met rien en cache. Avant de basculer :

  • Listez tout ce qui lit l'adresse de l'appelant, y compris les limites de débit, les listes d'autorisation, les signaux de fraude, les journaux d'audit et les règles de sécurité. Chacun voit l'adresse du point de présence tant que vous ne le changez pas.
  • Faites du nombre de couches de confiance une partie de votre infrastructure, et refusez de démarrer quand il est faux.
  • Laissez le point de présence enregistrer le véritable appelant, et ne faites confiance à cet enregistrement que sur le trafic dont vous pouvez vérifier qu'il vient de votre point de présence.
  • Assurez-vous que vos serveurs n'acceptent du trafic qu'à travers le point de présence, et observez avant d'appliquer.
  • Si vous mettez des pages en cache, construisez la clé de cache, l'ensemble des détails de requête qu'un cache utilise pour décider si deux requêtes peuvent partager une même réponse stockée, à partir de tout ce dont la réponse dépend réellement. Les serveurs listent ces détails dans un en-tête Vary, donc lisez-le plutôt que de vous fier à votre mémoire.
  • Mesurez avant et après, et examinez séparément le temps de handshake et le délai avant le premier octet, afin de distinguer l'établissement de la connexion du temps que vos serveurs passent à travailler.

Perspectives

La plupart de nos pages sont personnalisées, donc le cache périphérique du site web reste surtout inactif pour l'instant. L'amélioration de la connexion s'applique à chaque page quoi qu'il arrive, et chaque page peut désormais choisir la mise en cache lorsqu'il est sûr de la partager. Mettre en cache les réponses de l'API demanderait sa propre conception et sa propre relecture, et c'est la prochaine chose que nous voulons examiner.

L'argent devrait circuler à la vitesse du réseau, pas à la vitesse de la lumière à travers un océan.

Si vous construisez sur Moove, lisez notre introduction aux API et SDK de paiement Web3 et le Moove Developer Program.

Écrit par l'équipe d'ingénierie de moove.xyz.

À Propos De moove.xyz

moove.xyz est une plateforme fintech Web3 mondiale construite pour le mouvement de valeur sans permission et sans effort. Nous permettons aux entreprises et aux consommateurs partout dans le monde d'envoyer, de recevoir, de staker et d'échanger n'importe quelle cryptomonnaie sur n'importe quelle blockchain — le tout sur une seule plateforme.

Nous sommes l'une des premières entreprises fintech Web3 au monde à innover et à construire une infrastructure complète de paiements crypto et de finance décentralisée, permettant une couverture intégrée et complète de l'accès aux portefeuilles multi-chaînes, des identifiants de portefeuilles personnalisés, des échanges de tokens entre chaînes, des transactions intégrées entre chaînes et un réseau financier social décentralisé. Nos produits clés comprennent Moove Profile, Moove Send, Moove Receive, Moove Stake, Moove Swap, Moove Rewards, Moove Discover et bien d'autres.

Notre mission est simple — créer et distribuer une technologie financière sans permission et sans effort pour le prochain milliard d'utilisateurs Web3. Nous croyons fondamentalement que l'avenir du mouvement de l'argent et de la valeur sera sans coût, sans frontières, sans permission, sans effort et construit pour tous — et nous construisons la plateforme fintech Web3 ultime pour rendre cet avenir réel.

Votre argent. Votre mouvement.

APIs et SDKs de paiement Web3 : construire sur Moove
Guides

APIs et SDKs de paiement Web3 : construire sur Moove

16 juil. 20269 min de lecture
Tout ce qu'il faut savoir sur le Moove Developer Program
Guides
Gagner

Tout ce qu'il faut savoir sur le Moove Developer Program

6 sept. 20268 min de lecture
Moove App : paiements crypto sur iOS et Android
Points de vue

Moove App : paiements crypto sur iOS et Android

28 mars 20267 min de lecture

Votre argent. À vous de jouer.

Scannez pour télécharger l'app Moove
Télécharger dans l'App StoreDisponible sur Google Play