56

We're running a web app on Tomcat 6 and Apache mod_proxy 2.2.3. Seeing a lot of 502 errors like this:

Bad Gateway! The proxy server received an invalid response from an upstream server.

The proxy server could not handle the request GET /the/page.do.

Reason: Error reading from remote server

If you think this is a server error, please contact the webmaster.

Error 502

Tomcat has plenty of threads, so it's not thread-constrained. We're pushing 2400 users via JMeter against the app. All the boxes are sitting inside our firewall on a fast unloaded network, so there shouldn't be any network problems.

Anyone have any suggestions for things to look at or try? We're heading to tcpdump next.

UPDATE 10/21/08: Still haven't figured this out. Seeing only a very small number of these under load. The answers below haven't provided any magical answers...yet. :)

Alex Miller
  • 69,183
  • 25
  • 122
  • 167

10 Answers10

47

Just to add some specific settings, I had a similar setup (with Apache 2.0.63 reverse proxying onto Tomcat 5.0.27).

For certain URLs the Tomcat server could take perhaps 20 minutes to return a page.

I ended up modifying the following settings in the Apache configuration file to prevent it from timing out with its proxy operation (with a large over-spill factor in case Tomcat took longer to return a page):

Timeout 5400
ProxyTimeout 5400

Some backgound

ProxyTimeout alone wasn't enough. Looking at the documentation for Timeout I'm guessing (I'm not sure) that this is because while Apache is waiting for a response from Tomcat, there is no traffic flowing between Apache and the Browser (or whatever http client) - and so Apache closes down the connection to the browser.

I found that if I left the Timeout setting at its default (300 seconds), then if the proxied request to Tomcat took longer than 300 seconds to get a response the browser would display a "502 Proxy Error" page. I believe this message is generated by Apache, in the knowledge that it's acting as a reverse proxy, before it closes down the connection to the browser (this is my current understanding - it may be flawed).

The proxy error page says:

Proxy Error

The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET.

Reason: Error reading from remote server

...which suggests that it's the ProxyTimeout setting that's too short, while investigation shows that Apache's Timeout setting (timeout between Apache and the client) that also influences this.

Neil Salter
  • 271
  • 1
  • 3
  • 5
  • What is the syntax for timeout setting? TimeOut 5400 OR Timeout 5400? (small o vs capital O) – TechnoCrat Nov 05 '14 at 17:17
  • Configuration directives are case *insensitive* (but arguments may be case sensitive): http://httpd.apache.org/docs/2.4/configuring.html – sherb Nov 17 '14 at 19:05
  • Hello, I am fresher for this and don't know where to and how to set above property please explain me in detail. where I Can find this config file and where I have to write this property in that config file. – Uday A. Navapara Feb 25 '15 at 05:41
  • In my case, console dev of browser show me ......... 502 (Proxy Error)...... I added Timeout 5400 ProxyTimeout 5400 inside in file httpd.conf and WORKS!! Thanks! – JRichardsz Jul 04 '16 at 17:32
  • Adding the `ProxyTimeout` Directive would not be needed in most cases as it takes the `Timeout` Directives value as a default. See http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxytimeout – themenace Apr 18 '18 at 13:43
15

So, answering my own question here. We ultimately determined that we were seeing 502 and 503 errors in the load balancer due to Tomcat threads timing out. In the short term we increased the timeout. In the longer term, we fixed the app problems that were causing the timeouts in the first place. Why Tomcat timeouts were being perceived as 502 and 503 errors at the load balancer is still a bit of a mystery.

Alex Miller
  • 69,183
  • 25
  • 122
  • 167
  • Do you have any idea yet, why the load balancer throws bad gateways if the tomcat times out? – Tobias Apr 16 '13 at 07:38
  • In the documentation quoted in Janning's answer (http://stackoverflow.com/a/1287662/385571) the explanation is that there is a race condition between when the backend WAS closes the connection, and the mod_proxy_http checks it. If a new client connects without `proxy-initial-not-pooled` being set, it could be sent to this defunct thread. – MattBianco Sep 13 '16 at 11:26
12

You can use proxy-initial-not-pooled

See http://httpd.apache.org/docs/2.2/mod/mod_proxy_http.html :

If this variable is set no pooled connection will be reused if the client connection is an initial connection. This avoids the "proxy: error reading status line from remote server" error message caused by the race condition that the backend server closed the pooled connection after the connection check by the proxy and before data sent by the proxy reached the backend. It has to be kept in mind that setting this variable downgrades performance, especially with HTTP/1.0 clients.

We had this problem, too. We fixed it by adding

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

and turning keepAlive on all servers off.

mod_proxy_http is fine in most scenarios but we are running it with heavy load and we still got some timeout problems we do not understand.

But see if the above directive fits your needs.

Jan Dörrenhaus
  • 6,581
  • 2
  • 34
  • 45
Janning Vygen
  • 8,877
  • 9
  • 71
  • 102
  • This worked for me. I had inconsistent keep-alive settings which I corrected with SetEnv proxy-nokeepalive 1 and SetEnv force-proxy-request-1.0 1. – Ben Thurley Nov 14 '13 at 13:01
4

Sample from 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>
Devops-Paddy
  • 97
  • 1
  • 9
sibnick
  • 3,995
  • 20
  • 20
4

I know this does not answer this question, but I came here because I had the same error with nodeJS server. I am stuck a long time until I found the solution. My solution just adds slash or /in end of proxyreserve apache.

my old code is:

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

the correct code is:

ProxyPass / http://192.168.1.1:3001/
ProxyPassReverse / http://192.168.1.1:3001/
Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73
  • Thanks for sharing helped me fix a similar issue. – Joshua Achoka Oct 08 '20 at 08:49
  • works for me too. So now it makes me more confuse, is it a syntax issue [1] or timeout issue? [1]:ProxyPass / http://192.168.1.1:3001/ [1]:ProxyPassReverse / http://192.168.1.1:3001/ – yas Sep 14 '21 at 10:10
3

I'm guessing your using mod_proxy_http (or proxy balancer).

Look in your tomcat logs (localhost.log, or catalina.log) I suspect your seeing an exception in your web stack bubbling up and closing the socket that the tomcat worker is connected to.

Dave Cheney
  • 5,575
  • 2
  • 18
  • 24
  • Update the issue with anything you find in the log. Also check the apache error logs for, which should give you a clue who closed the socket (apache or tomcat). By default apache has a timeout of 300 seconds for proxied responses – Dave Cheney Oct 04 '08 at 06:46
3

You can avoid global timeouts or having to virtual hosts by specifying the proxy timeouts in the ProxyPass directive as follows:

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

Notice timeout=600 seconds.

However this does not always work when you have load balancer. In that case you must add the timeouts in both the places (tested in Apache 2.2.31)

Load Balancer example:

<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

A side note: the timeout=600 on ProxyPass was not required when Chrome was the client (I don;t know why) but without this timeout on ProxyPass Internet Explorer (11) aborts saying connection reset by server.

My theory is that the :

ProxyPass timeout is used between the client(browser) and the Apache.

BalancerMember timeout is used between the Apache and the backend.

To those who use Tomcat or other backed you may also want to pay attention to the HTTP Connector timeouts.

bhantol
  • 9,368
  • 7
  • 44
  • 81
2

you should be able to get this problem resolved through a timeout and proxyTimeout parameter set to 600 seconds. It worked for me after battling for a while.

tallguy
  • 1
  • 1
1

Most likely you should increase Timeout parameter in apache conf (default value 120 sec)

sibnick
  • 3,995
  • 20
  • 20
0

If you want to handle your webapp's timeout with an apache load balancer, you first have to understand the different meaning of timeout. I try to condense the discussion I found here: http://apache-http-server.18135.x6.nabble.com/mod-proxy-When-does-a-backend-be-considered-as-failed-td5031316.html :

It appears that mod_proxy considers a backend as failed only when the transport layer connection to that backend fails. Unless failonstatus/failontimeout is used. ...

So, setting failontimeout is necessary for apache to consider a timeout of the webapp (e.g. served by tomcat) as a fail (and consecutively switch to the hot spare server). For the proper configuration, note the following misconfiguration:

ProxyPass / balancer://localbalance/ failontimeout=on timeout=10 failonstatus=50

This is a misconfiguration because:

You are defining a balancer here, so the timeout parameter relates to the balancer (like the two others). However for a balancer, the timeout parameter is not a connection timeout (like the one used with BalancerMember), but the maximum time to wait for a free worker/member (e.g. when all the workers are busy or in error state, the default being to not wait).

So, a proper configuration is done like this

  1. set timeout at the BalanceMember level:
 <Proxy balancer://mycluster>
     BalancerMember http://member1:8080/svc timeout=6 
 ... more BalanceMembers here
</Proxy>
  1. set the failontimeout on the balancer
ProxyPass /svc balancer://mycluster failontimeout=on

Restart apache.

dr0i
  • 2,380
  • 2
  • 19
  • 36