Le défi de l'observabilité Serverless
Les outils traditionnels de surveillance des performances applicatives (APM) ont été conçus pour un monde de processus persistants. Dans ce monde, un serveur reste opérationnel pendant des jours ou des semaines, offrant un environnement stable pour la collecte de données. Cependant, les Azure Functions fonctionnent selon un paradigme totalement différent où les instances apparaissent et disparaissent en quelques millisecondes. Cette nature éphémère rend l'observabilité standard extrêmement difficile à l'échelle où nous opérons, avec plus de 72 millions de vérifications par mois.
Nous avons rapidement découvert qu'une journalisation verbeuse à ce volume est d'un coût prohibitif. Si nous laissions Application Insights sur ses paramètres par défaut, notre facture cloud serait dominée par les coûts d'ingestion de logs plutôt que par le calcul réel. De plus, les cold starts créent d'importants angles morts. Si une fonction ne parvient pas à démarrer ou expire pendant l'initialisation, elle ne laisse souvent aucune trace. On ne peut pas alerter sur une panne que l'on ne voit pas, c'est pourquoi nous avons dû construire une couche de surveillance architecturale et non seulement basée sur les logs.
Architecture : Découpler avec Service Bus
Pour gérer le débit massif requis pour une surveillance mondiale, nous avons découplé la planification des vérifications de leur exécution en utilisant Azure Service Bus. Dans notre architecture, un planificateur central écrit des messages de demande de vérification dans des files d'attente régionales. Les fonctions de travail régionales consomment ensuite ces messages indépendamment et exécutent les requêtes HTTP réelles. Ce modèle de déploiement en éventail est ce qui nous permet de traiter plus de 72 millions de vérifications par mois sans qu'un planificateur monolithique ne devienne un goulot d'étranglement.
Ce découplage offre également une immense résilience. Chaque région Azure dispose de sa propre file d'attente dédiée, ce qui signifie qu'une panne temporaire de worker à Singapour ne bloque pas les workers à Paris ou à Londres. Si un worker régional est submergé, les messages restent simplement dans la file d'attente jusqu'à ce que de la capacité soit disponible. Nous utilisons également des files d'attente de lettres mortes pour capturer les vérifications échouées qui ne peuvent pas être traitées après plusieurs tentatives, garantissant ainsi que nous ne perdons jamais de données et que nous pouvons enquêter sur la cause profonde des échecs d'exécution.
Stratégies d'optimisation des coûts
L'exécution de millions d'exécutions sur le plan de consommation Azure Functions signifie que chaque milliseconde et chaque entrée de log a un prix direct. Pour maintenir des coûts durables, nous avons mis en place une télémétrie structurée avec échantillonnage. Au lieu de journaliser chaque vérification réussie en détail, nous n'enregistrons les charges utiles complètes de requête et de réponse que lorsqu'une vérification échoue. Les succès sont enregistrés sous forme de métriques légères, fournissant les données nécessaires pour les pourcentages de disponibilité sans la surcharge de stockage.
L'interaction avec la base de données est un autre domaine critique pour le coût et la performance. Écrire une nouvelle ligne dans Azure SQL pour chaque vérification créerait une pression IOPS et une latence massives. Au lieu de cela, nos workers écrivent les lignes CheckResult par lots, mettant en mémoire tampon jusqu'est 50 résultats à la fois avant d'effectuer une insertion groupée. Enfin, le choix du bon niveau de Service Bus était essentiel. Bien que le niveau Standard soit suffisant pour les volumes inférieurs, nous sommes passés au niveau Premium pour la production à haut volume afin de garantir une latence prévisible et d'éviter la limitation du débit qui peut se produire sur une infrastructure partagée.
Gestion de la latence régionale
La latence réseau est l'ennemi d'une surveillance précise. Pour fournir des données fiables, nous déployons nos workers de surveillance dans les régions Azure les plus proches des endpoints surveillés. Cela réduit la variance du réseau et garantit que les temps de réponse que nous rapportons sont représentatifs des expériences réelles des utilisateurs. Pour atténuer l'impact des démarrages à froid sur les files d'attente critiques, nous utilisons le plan Azure Functions Premium pour nos workers les plus sensibles, en gardant un nombre minimum d'instances toujours actives et "pré-chauffées".
Nous devons également tenir compte de la latence ajoutée par l'infrastructure de surveillance elle-même. Nos workers mesurent le temps exact passé sur la requête HTTP et soustraient la surcharge interne avant de rapporter le résultat final. Les résultats multi-régions sont ensuite agrégés dans notre tableau de bord central. Pour qu'une vérification soit marquée comme "Healthy", nous pouvons configurer des règles où un nombre minimum de régions doivent répondre dans leurs seuils spécifiques, garantissant ainsi qu'une panne de fournisseur localisée n'est pas confondue avec une défaillance globale de l'API.
Leçons apprises
La construction de ContinuumNexus nous a appris que les événements personnalisés Application Insights, plutôt que les traces standard, sont le bon véhicule pour la télémétrie structurée des vérifications. Ils permettent des requêtes beaucoup plus propres et une meilleure intégration avec notre tableau de bord de reporting. Nous avons également appris à nos dépens que les tentatives de réexécution avec repli exponentiel sont essentielles pour les erreurs réseau transitoires. Rapporter une vérification comme échouée après une seule erreur 503 conduit à des faux positifs ; réessayer deux fois en cinq secondes offre une image beaucoup plus précise de l'indisponibilité réelle.
Notre enseignement le plus important est une philosophie simple : "Si vous construisez un outil de surveillance, surveillez-le de la même manière que vous surveillez les API de vos clients." La propre API de production et le tableau de bord de Continuum sont surveillés par notre propre moteur à partir de plusieurs régions. Cette boucle d'autosurveillance garantit que si notre infrastructure rencontre un problème, nous sommes les premiers informés. En traitant l'observabilité comme une exigence architecturale centrale plutôt que comme une réflexion après coup, nous avons construit une plateforme qui reste stable même si le nombre d'exécutions continue de grimper.


