Votre sonde de santé devrait interroger la base de données
L'affirmation Un point d'accès qui renvoie 200 sans condition est pire que l'absence de sonde. Il transforme une panne bruyante en panne silencieuse : votre répartiteur de charge c...
L'affirmation
Un point d'accès qui renvoie 200 sans condition est pire que l'absence de sonde. Il transforme une panne bruyante en panne silencieuse : votre répartiteur de charge continue d'acheminer le trafic vers un processus incapable de servir une seule requête, votre outil de surveillance reste au vert, et la première personne à s'en apercevoir est une cliente. Une sonde qui n'exerce pas ce qui risque le plus de casser est décorative.
Deux sondes, pas une
L'erreur courante consiste à faire porter deux rôles incompatibles au même point d'accès. Séparez-les :
- La vivacité répond à « ce processus est-il bloqué ? » Elle ne doit pas toucher la base de données. Si elle le fait, un hoquet passager de la base amène l'orchestrateur à tuer tous les conteneurs applicatifs d'un coup, transformant cinq secondes de dégradation en tempête de redémarrages.
- La disponibilité répond à « cette instance doit-elle recevoir du trafic maintenant ? » Elle doit toucher la base de données, le cache et tout ce sans quoi les requêtes échoueront.
La vivacité renvoie 200 si la boucle d'événements tourne. La disponibilité renvoie 503 quand une dépendance est tombée, ce qui retire l'instance de la rotation et l'y remet automatiquement au rétablissement.
À quoi ressemble une sonde de disponibilité
func readiness(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
http.Error(w, "db: "+err.Error(), http.StatusServiceUnavailable)
return
}
if err := cache.Ping(ctx).Err(); err != nil {
http.Error(w, "cache: "+err.Error(), http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
}
Trois détails distinguent une sonde utile d'un amplificateur de panne.
Le délai d'expiration est explicite et court. Deux secondes. Sans lui, une connexion bloquée à la base bloque la sonde elle-même, le répartiteur expire, et vous ne pouvez plus distinguer « lent » de « mort ».
Le corps de la réponse nomme la dépendance fautive. Pendant un incident, l'écart entre un 503 vide et db: connection refused vaut environ quinze minutes de votre soirée.
La requête est bon marché. Un SELECT 1 ou un ping du pilote. Si votre répartiteur sonde toutes les cinq secondes sur huit instances, cela fait 96 requêtes à la minute. Une sonde qui exécute une vraie requête d'affaires apparaîtra dans votre journal de requêtes lentes et, un mauvais jour, achèvera une base déjà en difficulté.
La dépendance qu'il ne faut pas vérifier
La disponibilité doit couvrir les dépendances sans lesquelles vous ne pouvez rien servir, et rien d'autre. La passerelle de paiement est l'erreur classique. Si Stripe passe un mauvais après-midi et que votre sonde l'interroge, chaque instance du parc annonce 503 et tout votre site s'éteint — y compris les pages qui n'ont rien à voir avec le paiement. Dégradez plutôt cette dépendance dans le gestionnaire de requête : affichez le catalogue, désactivez le bouton de paiement et laissez le reste du site continuer à produire.
Mettez le résultat en cache si le parc est grand
Au-delà d'une douzaine d'instances, ajoutez un cache en mémoire de courte durée sur la vérification des dépendances ; cinq secondes suffisent :
if time.Since(lastCheck) < 5*time.Second {
return cachedResult
}
Cela borne la charge que vos sondes imposent à une dépendance déjà mal en point, c'est-à-dire précisément au moment où vous voulez le moins lui ajouter 96 connexions par minute.
Configurez le répartiteur en conséquence
Le point d'accès n'est que la moitié du travail. Dans Nginx :
upstream app {
server 10.0.1.10:8080 max_fails=3 fail_timeout=15s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=15s;
}
Trois échecs avant le retrait, quinze secondes avant un nouvel essai. Un seul échec est trop nerveux : un paquet perdu ne devrait pas éjecter une instance en santé. Trente secondes de tolérance sont trop lentes : vous servez des erreurs pendant tout ce temps. Trois sondes à cinq secondes d'intervalle retirent une instance réellement morte en une quinzaine de secondes, ce qui est un compromis raisonnable.
Ce qu'il faut vérifier de l'extérieur
Votre surveillance externe ne devrait pas frapper la sonde de disponibilité. Elle devrait charger une vraie page et vérifier son contenu :
curl -fsS https://exemple.ca/produits | grep -q 'Ajouter au panier' || exit 1
Cela attrape la catégorie de panne qu'aucune sonde interne ne voit : l'application fonctionne, la base fonctionne, et un mauvais déploiement a remplacé le catalogue par une page vide. Nous avons vu un site rester dans cet état deux jours avec une disponibilité rapportée de 100 %, parce que chaque sonde de la pile demandait si le serveur répondait plutôt que s'il répondait correctement.
Une courte liste de contrôle
- La vivacité ne vérifie rien d'externe. La disponibilité vérifie chaque dépendance dure.
- Chaque vérification de dépendance a un délai explicite sous les trois secondes.
- Les échecs renvoient 503 avec le nom de la dépendance dans le corps.
- Les résultats de disponibilité sont mis en cache quelques secondes sur les grands parcs.
- Au moins une sonde externe vérifie le contenu de la page, pas le code de statut.
Rien de tout cela ne prend plus d'un après-midi. Le gain, c'est que votre surveillance cesse de vous donner raison quand vous avez tort.