Résolution des problèmes de timeout 504 Gateway Timeout et de timeout client avec Nginx
Nginx, bien que connu pour ses hautes performances et sa stabilité, peut parfois présenter des erreurs frustrantes, notamment des codes d'état HTTP indiquant une rupture de communication. Parmi les plus courants figurent les erreurs 504 Gateway Timeout et divers timeouts côté client. Ces problèmes découlent presque toujours d'une inadéquation entre le temps pendant lequel Nginx attend une réponse d'un service backend (comme un serveur d'application ou un autre proxy) et le temps pendant lequel le client (navigateur ou service amont) est prêt à attendre Nginx lui-même.
Ce guide complet vous accompagnera dans le diagnostic de la cause profonde de ces timeouts et vous proposera des ajustements de configuration concrets pour résoudre les erreurs 504 et améliorer la stabilité globale des connexions. Comprendre ces mécanismes est crucial pour maintenir une haute disponibilité, en particulier dans les architectures de microservices ou lors de la gestion d'applications amont lentes à répondre.
Comprendre l'erreur 504 Gateway Timeout
Une erreur 504 Gateway Timeout se produit lorsque Nginx, agissant comme un proxy inverse ou une passerelle, ne reçoit pas de réponse rapide du serveur amont vers lequel il transfère les requêtes. En termes simples : Nginx a demandé une réponse au backend, a attendu le temps configuré, et a abandonné car aucune réponse n'est arrivée.
Cela est distinct d'un 502 Bad Gateway (qui implique une réponse invalide du serveur amont) ou d'un 503 Service Unavailable (qui implique que le serveur amont est actuellement surchargé ou indisponible).
Directives clés contrôlant les timeouts amont
Lors du proxy de requêtes, Nginx utilise plusieurs directives critiques, principalement situées dans les blocs http, server ou location, ou spécifiquement dans un bloc upstream. L'ajustement de ces valeurs est la principale méthode pour résoudre les erreurs 504.
1. proxy_connect_timeout
Définit le timeout pour l'établissement d'une connexion avec le serveur amont. Si Nginx ne parvient pas à se connecter dans ce délai, il renvoie une erreur de timeout.
Défaut : 60 secondes
proxy_connect_timeout 60s;
2. proxy_send_timeout
Définit le timeout pour le temps écoulé entre deux opérations d'écriture successives vers le serveur amont. Ceci est pertinent lors de l'envoi d'un corps de requête volumineux.
Défaut : 60 secondes
proxy_send_timeout 60s;
3. proxy_read_timeout (La correction la plus fréquente pour les 504)
Définit le timeout pour l'attente d'une réponse du serveur amont après l'envoi des en-têtes de requête. Si l'application backend prend trop de temps pour traiter la requête et générer un corps de réponse, c'est cette directive qui doit être augmentée.
Défaut : 60 secondes
# Exemple : Augmentation du timeout de lecture à 120 secondes pour une API lente
proxy_read_timeout 120s;
Bonne pratique : Si votre application dépasse fréquemment les 60 secondes par défaut, augmentez cette valeur avec prudence. Une valeur très élevée pourrait masquer des problèmes de performance fondamentaux du backend.
Traiter les timeouts côté client
Alors que le 504 concerne la communication Nginx-Backend, les timeouts côté client se produisent lorsque le client (par exemple, un navigateur, une application mobile ou un autre service effectuant une requête vers Nginx) abandonne l'attente avant même que Nginx ait fini de communiquer avec le backend.
Si vous rencontrez des timeouts client avant que Nginx n'enregistre un 504, vous devez examiner la connexion entre le client et Nginx.
1. Keepalive côté client
Si le client ferme la connexion prématurément, Nginx peut recevoir une erreur ou le client peut simplement avoir un timeout en attendant les données.
Assurez-vous que vos paramètres de connexion côté client (si configurables) ne sont pas trop agressifs. Si le client est un autre proxy ou un équilibreur de charge, vérifiez ses paramètres de timeout par rapport au send_timeout de Nginx.
2. send_timeout de Nginx
Cette directive contrôle le temps pendant lequel Nginx attend que le client accuse réception ou reçoive des données (le temps entre deux opérations d'écriture successives vers le client).
Défaut : 60 secondes
# Définissez ceci si les clients ont un timeout pendant que Nginx envoie la réponse
send_timeout 120s;
Optimisation de la mise en mémoire tampon pour les réponses volumineuses
Parfois, les timeouts ne se produisent pas parce que le traitement a pris trop de temps, mais parce que Nginx a commencé à mettre en mémoire tampon la réponse du serveur amont, puis n'a pas réussi à terminer l'écriture dans le tampon avant l'expiration du délai de connexion. Ceci est particulièrement pertinent lorsqu'on traite des réponses très volumineuses.
Nginx utilise des tampons pour conserver temporairement les données reçues du serveur amont avant de les envoyer au client. Si la réponse est très volumineuse, ces tampons peuvent être dépassés, entraînant une gestion complexe ou une latence perçue.
Directives clés de mise en mémoire tampon
Celles-ci sont généralement définies dans le bloc location ou server :
| Directive | But |
|---|---|
proxy_buffers |
Définit le nombre et la taille des tampons utilisés pour lire l'en-tête de réponse du serveur amont. Format : nombre taille; |
proxy_buffer_size |
Définit la taille du premier tampon, qui est utilisé pour lire l'en-tête de réponse. |
proxy_max_temp_file_size |
Si la réponse dépasse les tampons disponibles, Nginx écrit dans des fichiers temporaires. Ceci définit la taille maximale de ces fichiers temporaires. |
Exemple de configuration pour un volume élevé / réponses volumineuses :
location /api/heavy_report {
proxy_pass http://backend_app;
# Augmenter le timeout de lecture
proxy_read_timeout 180s;
# Ajuster la mise en mémoire tampon pour des corps de réponse potentiellement volumineux
# Utiliser 8 tampons, chacun jusqu'à 1 Mo (1024k)
proxy_buffers 8 1024k;
proxy_buffer_size 256k;
# Autoriser des fichiers temporaires jusqu'à 500 Mo si les tampons débordent
proxy_max_temp_file_size 500m;
}
Astuce sur la mise en mémoire tampon : Si la réponse de votre backend est véritablement énorme (par exemple, plusieurs Go), envisagez de servir du contenu statique ou de mettre en œuvre un streaming direct, car la mise en mémoire tampon de réponses extrêmement volumineuses peut consommer une quantité significative de mémoire sur le serveur Nginx.
Étapes de dépannage et analyse des journaux
La résolution des timeouts nécessite d'identifier précisément où s'est produit le blocage : Client -> Nginx, ou Nginx -> Backend.
Étape 1 : Vérifier les journaux d'erreurs de Nginx
Le journal d'erreurs de Nginx est votre source définitive pour déterminer si Nginx a eu un timeout en attendant le backend.
Recherchez des entrées contenant des phrases telles que :
upstream timed out (110: Connection timed out)upstream prematurely closed connection while reading response header from upstream
Si vous voyez ces messages, le problème réside dans proxy_read_timeout ou dans le temps de traitement du backend.
Étape 2 : Vérifier les journaux de l'application backend
Si Nginx rencontre un timeout (les journaux indiquent 504), vérifiez immédiatement les journaux du service amont (par exemple, les journaux PHP-FPM, les journaux Gunicorn, les journaux du serveur d'applications Java). Vous devez confirmer si la requête a bien atteint le backend et combien de temps elle a pris pour s'exécuter.
- Si les journaux du backend montrent que la requête a pris plus de temps que votre
proxy_read_timeoutconfiguré, augmentez le timeout de Nginx. - Si les journaux du backend montrent que la requête s'est terminée rapidement, le problème pourrait être la latence réseau entre Nginx et le backend, ou un timeout client mal configuré face à Nginx.
Étape 3 : Utiliser l'en-tête X-Upstream-Response-Time (Optionnel)
Pour des diagnostics détaillés, vous pouvez enregistrer le temps exact pris par le serveur amont pour répondre en utilisant la variable $upstream_response_time dans le format de votre journal d'accès. Cela permet de confirmer les performances réelles du backend.
Dans votre nginx.conf :
log_format proxy_detailed '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time $upstream_response_time';
access_log /var/log/nginx/access.log proxy_detailed;
En analysant $upstream_response_time, vous pouvez voir la durée précise pendant laquelle Nginx a attendu, indépendamment des propres paramètres de timeout de Nginx.
Résumé et application des changements
La résolution des problèmes de timeout Nginx implique généralement un équilibre entre les attentes des clients et les capacités de traitement du backend. Rappelez-vous de la relation :
- Timeout 504 : Le backend est trop lent ou le lien réseau a échoué pendant que Nginx attendait (
proxy_read_timeout). - Timeout client : Le client a abandonné l'attente de Nginx (
send_timeoutou paramètre client).
Après avoir effectué des modifications de configuration (par exemple, augmenter les timeouts ou ajuster les tailles de tampons), testez toujours la syntaxe de configuration et rechargez Nginx :
sudo nginx -t
sudo systemctl reload nginx
Surveillez attentivement vos journaux après l'application des correctifs, car augmenter aveuglément les timeouts peut masquer des goulots d'étranglement de performance système sous-jacents qui nécessitent une optimisation plutôt que des solutions de contournement de configuration.