Apache mod_proxy和Tomcat出现错误的网关502错误

我们正在Tomcat 6和Apache mod_proxy 2.2.3上运行一个Web应用程序。 看到很多像这样的502错误:

错误的网关! 代理服务器收到来自上游服务器的无效响应。

代理服务器无法处理请求GET / the / page.do。

原因:从远程服务器读取错误

如果您认为这是服务器错误,请与网站站长联系。

错误502

Tomcat有很multithreading,所以不是线程受限的。 我们通过JMeter推送了2400个用户对应用程序。 所有的盒子都坐在我们的防火墙内,在一个快速卸载的networking上,所以不应该有任何networking问题。

任何人有任何build议,看看或尝试? 接下来我们要转到tcpdump。

更新10/21/08:还没有想通了。 只能看到很less的这些负载。 下面的答案还没有提供任何神奇的答案。 🙂

只是添加一些特定的设置,我有一个类似的设置(与Apache 2.0.63反向代理到Tomcat 5.0.27)。

对于某些URL,Tomcat服务器可能需要20分钟才能返回页面。

我最终修改了Apacheconfiguration文件中的以下设置,以防止它的代理操作超时(在Tomcat花费更长的时间返回一个页面时,溢出因子很大):

Timeout 5400 ProxyTimeout 5400 

一些背景

只有ProxyTimeout是不够的。 看看Timeout的文档我 (我不确定),这是因为当Apache正在等待来自Tomcat的响应时,Apache和浏览器(或任何HTTP客户端)之间没有stream量 – 等等Apacheclosures了与浏览器的连接。

我发现,如果我将超时设置保留为默认值(300秒),那么如果向Tomcat的代理请求花费了超过300秒的时间来获得响应,浏览器将显示“502代理错误”页面。 我相信这个消息是由Apache产生的,在知道它是一个反向代理之前,它closures了与浏览器的连接(这是我目前的理解 – 这可能是有缺陷的)。

代理错误页面说:

代理错误

代理服务器收到来自上游服务器的无效响应。 代理服务器无法处理请求GET。

原因:从远程服务器读取错误

…这表明它的ProxyTimeout设置太短,而调查显示Apache的超时设置(Apache和客户端之间的超时)也影响到这一点。

所以,在这里回答我自己的问题。 我们最终确定,由于Tomcat线程超时,负载均衡器中出现502和503错误。 在短期内,我们增加了超时时间。 从长远来看,我们首先解决了导致超时的应用程序问题。 为什么Tomcat超时被认为是负载均衡器中的502和503错误仍然是一个谜。

你可以使用proxy-initial-not-pooled

请参阅http://httpd.apache.org/docs/2.2/mod/mod_proxy_http.html

如果设置了这个variables,如果客户端连接是初始连接,则不会重用池连接。 这样可以避免在代理进行连接检查之后,代理发送的数据到达后端之前,由后端服务器closures池连接的争用条件引起的“远程服务器的代理:错误读取状态行”错误消息。 必须记住,设置这个variables会降低性能,特别是对于HTTP / 1.0客户端。

我们也有这个问题。 我们通过添加SetEnv proxy-nokeepalive 1 SetEnv proxy-initial-not-pooled 1和truning keepAliveclosures所有服务器来修复它。

mod_proxy_http在大多数szenarios中都是正常的,但是我们在负载很重的情况下运行它,而且我们仍然有一些我们不明白的超时问题。

但看看上面的指令是否符合你的需求。

我猜你正在使用mod_proxy_http(或代理平衡器)。

看看你的Tomcat日志(localhost.log,或catalina.log)我怀疑你的web堆栈中看到一个exception,冒泡和closurestomcat worker连接到的套接字。

来自apache conf的示例:

#默认值是2分钟。
超时600
ProxyRequestsclosures
ProxyPass / app平衡器:// MyApp stickysession = JSESSIONID lbmethod = bytraffic nofailover = On
ProxyPassReverse /应用程序平衡器:// MyApp
ProxyTimeout 600
<代理平衡器:// MyApp>
BalancerMember http:// node1:8080 / route = node1 retry = 1 max = 25 timeout = 600
………
</代理>

最有可能你应该增加Apache的configurationTimeout参数(默认值120秒)

您应该能够通过超时和proxyTimeout参数设置为600秒来解决此问题。 经过一段时间之后,它对我有用。

您可以通过在ProxyPass指令中指定代理超时来避免全局超时或不得不虚拟主机,如下所示:

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

通知timeout=600秒。

但是,当你有负载均衡器时,这并不总是奏效。 在这种情况下,您必须在两个地方添加超时(在Apache 2.2.31中testing)

负载平衡器示例:

 <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 

一个侧面说明:当Chrome是客户端(我不知道为什么)时, ProxyPass上的timeout=600并不是必需的,但在ProxyPass Internet Explorer(11)上没有这个超时会中止服务器重置连接。

我的理论是:

客户端(浏览器)和Apache之间使用ProxyPass超时。

在Apache和后端之间使用BalancerMember超时。

对于那些使用Tomcat或其他支持的用户,您可能还需要注意HTTP连接器超时。