ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

Health Check

L'endpoint que tout le monde croit trivial — et qui, mal conçu, casse l'auto-healing infrastructure. Liveness, readiness, startup : trois questions différentes.

Problème

Un service EDI démarre en chargeant 200 Mo de schémas EDIFACT, établit une connexion à Kafka et à Redis. Pendant ce warmup de 15s, Kubernetes envoie un GET / qui renvoie 200 : le Pod est marqué Ready et reçoit du trafic. Les premières requêtes plantent en NPE « schémas non chargés ». Pire : en production, un schéma corrompu fait planter le parser à chaque requête, mais le process reste vivant — Kubernetes ne kill jamais le Pod parce que /health répond toujours 200. Le Pod est zombie.

Forces

  • Plusieurs questions différentes : le process tourne-t-il ? Peut-il accepter du trafic maintenant ? A-t-il fini de démarrer ?
  • L'orchestrateur agit différemment selon la réponse. Liveness fail → restart Pod. Readiness fail → retirer du LB. Startup fail → attendre encore.
  • Le health doit être bon marché. Interrogé toutes les 5-10s par Pod. Pas de query DB lourde.
  • Le health peut mentir. Si on teste « est-ce que je peux pinger Kafka », un partenaire externe down nous fait dire ready=false. Distinguer dépendance critique vs optionnelle.

Solution

Exposer trois endpoints distincts : /health/live (le process est vivant — test minimal, ne touche aucune dépendance, juste « je peux répondre à un HTTP »), /health/ready (prêt à recevoir du trafic — vérifie dépendances critiques : DB, broker, schémas chargés), /health/startup (démarrage terminé — utile pour les apps lentes au boot). Format de réponse : suivre l'IETF draft Health Check Response Format ou Microsoft Health Endpoint. Sur Kubernetes : configurer livenessProbe, readinessProbe, startupProbe avec les bons paramètres (periodSeconds, failureThreshold).

Trois endpoints distincts (RFC Health Check Response Format) :

  GET /health/live    → liveness
    200 = "process vivant, ne pas kill"
    503 = "process zombie, redémarrer"

  GET /health/ready   → readiness
    200 = "prêt à recevoir du trafic"
    503 = "warmup en cours / dépendance down / drain"
    → si 503, le LB retire le Pod du round-robin

  GET /health/startup → startup
    200 = "initialisation terminée"
    503 = "encore en train de charger les schémas EDIFACT"
    → bloque les autres probes pendant le démarrage

  Réponse JSON RFC :
  {
    "status": "pass" | "warn" | "fail",
    "version": "1.4.2",
    "checks": {
      "kafka": { "status": "pass", "time": "2026-05-16T08:30:00Z" },
      "redis": { "status": "pass" },
      "as2.walmart": { "status": "warn", "observedValue": 12s }
    }
  }

Implémentation EDI

Cas concret : service parser EDIFACT en Spring Boot avec Spring Boot Actuator. /actuator/health/liveness renvoie 200 sauf si le process est dans un état non-recoverable (OutOfMemoryError, deadlock détecté). /actuator/health/readiness vérifie : connexion Kafka producer, connexion Redis cache, schémas EDIFACT D.96A/D.01B/D.24A chargés, état du Circuit Breaker vers Walmart (si ouvert depuis > 30 min → warn, sinon pass). /actuator/health/startup renvoie 503 tant que les schémas ne sont pas chargés (jusqu'à 90s). Sur Kubernetes, startupProbe.failureThreshold=30 × periodSeconds=5s = grace period 2,5 min avant abandon. Pour PEPPOL Access Point, le health doit aussi vérifier la rotation des certificats AS4 — un cert expiré rend l'AP inutilisable même si le process tourne.

Anti-patterns

  • Un seul /health. Mélanger liveness et readiness signifie qu'une dépendance externe down fait restart le Pod en boucle (qui n'aide en rien).
  • Health qui exécute du business logic. « Je teste en envoyant un INVOIC réel à Walmart » : pollue le log audit du partenaire, peut violer SLA.
  • Health caché derrière auth. Le kubelet ne peut pas s'authentifier facilement. Exposer en network policy interne sans auth.
  • Health qui interroge toutes les dépendances en cascade. Si le check d'une dépendance prend 30s, le health timeout, le Pod est restart à tort.
  • Cascade de readiness. Service A ready=false si service B ready=false : une panne se propage en arrière. Distinguer dépendance critique (échec si absente) vs dégradation gracieuse.

Patterns liés

Sources