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.

Timeout

La promesse explicite : « si pas de réponse en X secondes, j'abandonne ». Le pattern qui empêche les pannes silencieuses de tout bloquer.

Problème

Un service hub appelle l'API AS2 d'un partenaire pour envoyer un INVOIC. Le partenaire est en train de redémarrer son serveur. La connexion TCP est ouverte mais aucune réponse HTTP n'arrive. Sans timeout, le thread est bloqué indéfiniment. Le client HTTP par défaut (Java OkHttp, Apache HTTPClient, Node.js fetch) n'a pas de timeout actif par défaut. Au bout d'une heure, on a 200 threads bloqués, le pool est saturé, plus aucune requête nouvelle ne passe. Le partenaire est mort, le hub aussi.

Forces

  • Une attente non bornée transforme une lenteur en panne. C'est le piège classique du réseau distribué.
  • Les couches du réseau ont des temporalités différentes. Connect = quelques secondes, read = minutes selon volume.
  • Le bon timeout dépend du contexte. AS2 batch INVOIC géant tolère 5 min ; API REST de validation, 5 s.
  • Le timeout est invisible aux deux côtés. Le partenaire continue de travailler côté serveur, le client a déjà abandonné — d'où l'importance de l'idempotence.

Solution

Définir explicitement chaque timeout : connect (établir la connexion), read/socket (recevoir un octet sans nouvel envoi), request total (round-trip complet). Configurer chaque couche cliente, broker, middleware. Documenter par partenaire : Walmart accepte 30s, PEPPOL recommande 60s, Stellantis 120s. Mesurer les latences p95/p99 réelles et caler le timeout à p99 + 50% de marge. Logger chaque timeout pour distinguer panne partenaire vs configuration trop agressive.

Stack des timeouts pour une requête AS2 sortante :

  ┌─────────────────────────────────────────────┐
  │ 1. DNS lookup        : timeout    2 s       │
  │ 2. TCP connect       : timeout    5 s       │
  │ 3. TLS handshake     : timeout   10 s       │
  │ 4. HTTP request send : timeout   30 s       │
  │ 5. HTTP read body    : timeout   60 s       │
  │ 6. MDN ack reception : timeout  120 s       │
  │ 7. Total round-trip  : timeout  180 s       │
  └─────────────────────────────────────────────┘

  Chaque borne est un kill-switch local. Le total
  est la borne « contrat partenaire ». Sans 7, on
  peut additionner 1-6 et attendre 4 min sur un
  trafic mort.

Implémentation EDI

Cas concret : en Java/Spring, configuration RestTemplate ou WebClient avec connectTimeout=5s, readTimeout=60s. Sur OkHttp : callTimeout=180s. Pour AS2 : Mendelson, Sterling, OpenAS2 exposent des paramètres connection.timeout, read.timeout, mdn.timeout. Côté SFTP : JSCH avec session.timeout + channel.timeout séparés. Sur Kafka producer : request.timeout.ms=30000, delivery.timeout.ms=120000. Sur API Gateway (Kong) : timeouts upstream paramétrables par route. Et crucial : timeout côté serveur HTTP (Tomcat connectionTimeout, Netty READ_TIMEOUT) pour ne pas se laisser surcharger par un client lent (slow loris).

Anti-patterns

  • Pas de timeout. La valeur « par défaut » est souvent infinie. Le piège classique.
  • Timeout unique global. timeout=30s pour tout : un INVOIC géant légitimement long est tué, et un appel REST instantané attend 30s en cas de panne.
  • Timeout sans idempotence. Le client abandonne à 10s, le partenaire commit à 10.1s : doublon créé au retry (sans idempotence).
  • Timeout trop agressif. p99 réel = 45s, timeout = 30s : on retry trop, on amplifie les pannes (retry storm).
  • Timeout sans propagation. Service A appelle B avec timeout 30s, B appelle C avec timeout 60s : A abandonne avant que B finisse. Propager le timeout (deadline propagation).

Patterns liés

  • Circuit Breaker — les timeouts répétés ouvrent le circuit.
  • Retry + backoff — chaque retry a son propre timeout.
  • Idempotence — indispensable car timeout ≠ panne : la requête a peut-être commit.
  • Bulkhead — sans timeout, l'isolation des compartiments ne suffit pas.
  • Dead Letter Channel — destination des messages dont les retries ont tous timeout.

Sources