web-dev-qa-db-fra.com

Erreur Bad Gateway 502 avec Apache mod_proxy et Tomcat

Nous exécutons une application Web sur Tomcat 6 et Apache mod_proxy 2.2.3. Voir beaucoup d'erreurs 502 comme ceci:

Mauvaise passerelle! Le serveur proxy a reçu une réponse non valide d'un serveur en amont.

Le serveur proxy n'a pas pu traiter la demande GET /the/page.do.

Raison: erreur de lecture à partir du serveur distant

Si vous pensez qu'il s'agit d'une erreur de serveur, veuillez contacter le webmaster.

Erreur 502

Tomcat a beaucoup de threads, il n'est donc pas contraint aux threads. Nous poussons 2400 utilisateurs via JMeter contre l'application. Toutes les boîtes se trouvent à l'intérieur de notre pare-feu sur un réseau rapidement déchargé, il ne devrait donc pas y avoir de problèmes de réseau.

Quelqu'un a-t-il des suggestions de choses à regarder ou à essayer? Nous nous dirigeons vers tcpdump ensuite.

MISE À JOUR 21/10/08: Je n'ai toujours pas compris cela. Ne voir qu'un très petit nombre de ceux-ci sous charge. Les réponses ci-dessous n'ont pas encore fourni de réponses magiques. :)

46
Alex Miller

Donc, répondre à ma propre question ici. Nous avons finalement déterminé que nous voyions des erreurs 502 et 503 dans l'équilibreur de charge en raison de l'expiration des threads Tomcat. À court terme, nous avons augmenté le délai d'attente. À plus long terme, nous avons résolu les problèmes d'application à l'origine des délais d'attente. La raison pour laquelle les délais d'attente Tomcat étaient perçus comme des erreurs 502 et 503 au niveau de l'équilibreur de charge est encore un peu mystérieuse.

13
Alex Miller

Juste pour ajouter des paramètres spécifiques, j'avais une configuration similaire (avec le proxy inverse Apache 2.0.63 sur Tomcat 5.0.27).

Pour certaines URL, le serveur Tomcat peut prendre jusqu'à 20 minutes pour renvoyer une page.

J'ai fini par modifier les paramètres suivants dans le fichier de configuration Apache pour l'empêcher de se terminer avec son opération proxy (avec un grand facteur de débordement au cas où Tomcat mettrait plus de temps à renvoyer une page):

Timeout 5400
ProxyTimeout 5400

Quelques backgound

ProxyTimeout seul n'était pas suffisant. En regardant la documentation de Timeout je devine (je ne suis pas sûr) que c'est parce que pendant qu'Apache attend pour une réponse de Tomcat, il n'y a pas de trafic entre Apache et le navigateur (ou tout autre client http) - et donc Apache ferme la connexion au navigateur.

J'ai constaté que si je laissais le paramètre Délai d'expiration à sa valeur par défaut (300 secondes), si la demande de proxy à Tomcat prenait plus de 300 secondes pour obtenir une réponse, le navigateur afficherait une page "Erreur de proxy 502". Je crois que ce message est généré par Apache, sachant qu'il agit comme un proxy inverse, avant de fermer la connexion au navigateur (c'est ma compréhension actuelle - il peut être défectueux).

La page d'erreur du proxy indique:

Erreur proxy

Le serveur proxy a reçu une réponse non valide d'un serveur en amont. Le serveur proxy n'a pas pu gérer la demande GET.

Raison: erreur de lecture à partir du serveur distant

... ce qui suggère que c'est le paramètre ProxyTimeout qui est trop court, tandis que l'enquête montre que le paramètre Timeout d'Apache (délai entre Apache et le client) qui influence également cela.

42
Neil Salter

Vous pouvez utiliser proxy-initial-not-pooled

Voir http://httpd.Apache.org/docs/2.2/mod/mod_proxy_http.html :

Si cette variable est définie, aucune connexion groupée ne sera réutilisée si la connexion client est une connexion initiale. Cela évite le message d'erreur "proxy: erreur de lecture de la ligne d'état du serveur distant" provoqué par la condition de concurrence critique selon laquelle le serveur d'arrière-plan a fermé la connexion groupée après la vérification de connexion par le proxy et avant que les données envoyées par le proxy n'atteignent le backend. Il faut garder à l'esprit que la définition de cette variable réduit les performances, en particulier avec les clients HTTP/1.0.

Nous avons aussi eu ce problème. Nous l'avons corrigé en ajoutant

SetEnv proxy-nokeepalive 1
SetEnv proxy-initial-not-pooled 1

et désactiver keepAlive sur tous les serveurs.

mod_proxy_http est correct dans la plupart des scénarios, mais nous l'exécutons avec une charge élevée et nous avons toujours des problèmes de délai d'attente que nous ne comprenons pas.

Mais voyez si la directive ci-dessus correspond à vos besoins.

9
Janning

Exemple d'Apache conf:

#Default value is 2 minutes
**Timeout 600**
ProxyRequests off
ProxyPass /app balancer://MyApp stickysession=JSESSIONID lbmethod=bytraffic nofailover=On
ProxyPassReverse /app balancer://MyApp
ProxyTimeout 600
<Proxy balancer://MyApp>
    BalancerMember http://node1:8080/ route=node1 retry=1 max=25 timeout=600
    .........
</Proxy>
3
sibnick

Vous pouvez éviter les délais d'expiration globaux ou avoir à des hôtes virtuels en spécifiant les délais d'expiration du proxy dans la directive ProxyPass comme suit:

ProxyPass /svc http://example.com/svc timeout=600
ProxyPassReverse /svc http://example.com/svc timeout=600

Remarquer timeout=600 secondes.

Cependant, cela ne fonctionne pas toujours lorsque vous disposez d'un équilibreur de charge. Dans ce cas, vous devez ajouter les délais d'expiration aux deux endroits (testé dans Apache 2.2.31)

Exemple d'équilibreur de charge:

<Proxy "balancer://mycluster">
     BalancerMember "http://member1:8080/svc" timeout=600
     BalancerMember "http://member2:8080/svc" timeout=600
</Proxy> 

ProxyPass /svc "balancer://mycluster" timeout=600
ProxyPassReverse /svc "balancer://mycluster" timeout=600

Une note latérale: le timeout=600 sur ProxyPass n'était pas requis lorsque Chrome était le client (je ne sais pas pourquoi)) mais sans ce délai sur ProxyPass Internet Explorer (11) annule la réinitialisation de la connexion par le serveur.

Ma théorie est que:

ProxyPass timeout est utilisé entre le client (navigateur) et Apache.

BalancerMember timeout est utilisé entre Apache et le backend.

Pour ceux qui utilisent Tomcat ou un autre support, vous pouvez également faire attention aux délais d'expiration du connecteur HTTP.

3
bhantol

vous devriez pouvoir résoudre ce problème via un paramètre de délai d'expiration et de proxyTimeout défini sur 600 secondes. Cela a fonctionné pour moi après avoir lutté pendant un certain temps.

2
tallguy

Je suppose que vous utilisez mod_proxy_http (ou proxy balancer).

Regardez dans vos journaux Tomcat (localhost.log ou catalina.log) Je soupçonne que vous voyez une exception dans votre pile Web bouillonner et fermer le socket auquel le travailleur Tomcat est connecté.

2
Dave Cheney

Vous devriez probablement augmenter le paramètre Timeout dans Apache conf (valeur par défaut 120 sec)

1
sibnick

Je sais que cela ne répond pas à cette question, mais je suis venu ici parce que j'ai eu la même erreur avec le serveur nodeJS. Je suis coincé longtemps jusqu'à ce que je trouve la solution. Ma solution ajoute simplement une barre oblique ou /en fin de proxyreserve Apache.

mon ancien code est:

ProxyPass / http://192.168.1.1:3001
ProxyPassReverse / http://192.168.1.1:3001

le bon code est:

ProxyPass / http://192.168.1.1:3001/
ProxyPassReverse / http://192.168.1.1:3001/