来自 Elastic Load Balancer 使用 Tomcat 的 504 错误
504 errors from Elastic Load Balancer using Tomcat
我在多个 EC2 实例上有一个应用程序 运行,由 Apache Tomcat 提供服务。我在应用程序前面设置了一个 AWS Elastic Load Balancer,一切基本上都按预期工作。但是,我偶尔会从 ELB 收到随机的 504 超时错误。这似乎与负载无关,因为我看到了轻负载和重负载下的错误。此外,它似乎不会在任何常规模式或情况下发生。
在我早些时候的测试中,我遇到了 504 错误,因为我的应用程序响应时间比 ELB 上默认的 60 秒超时时间长。我通过将 ELB 超时提高到我的应用程序所需的级别来解决这个问题。但是,我现在遇到的 504 错误发生得非常快。因此,例如,我看到的一个错误是关于响应时间约为一秒的请求。当请求不可能在应用程序服务器上超时时出现超时错误似乎很奇怪。
这可能是一个与 this question 类似的问题,尽管我无法从提供的信息中完全分辨出来。另外,我没有额外的负载均衡器,只是 ELB 直接到 Tomcat.
ELB 不太可能是问题的原因,而是表明您有问题。 504 错误是 Gateway Timeout,当服务器(在本例中 Tomcat)响应不够快时发生。
(我多年来一直将 ELB 用于极高负载服务,并且不同意 link 对其他 SO 答案的回答。虽然这在技术上是正确的,并且可能是正确的非常高爆率,一秒上千个请求,除非你的量这么大,我先看看你的申请。)
确认它不是 ELB 的最明显测试是直接针对集群中的 Tomcat 服务器之一测试请求。如果您无法路由到 Tomcat 个实例,您可以尝试从您要测试的实例 curl
到本地主机。
另请注意,ELB 有一个健康检查设置,这些设置允许您设置某些规则来定义服务器是否健康——如果不健康,ELB 将从集群中删除它,直到它再次健康。健康可以包括及时的反应。查看ELB的CloudWatch,看看最近有没有不健康的实例。
如果您在开发中看到 504,而现在它更频繁了,我猜这实际上是一个负载或性能问题。最典型的是 Java 由于底层应用程序的问题而陷入一些垃圾收集抖动问题。查看您的 EC2 实例的 CloudWatch 指标,了解内存或 CPU 是否过高或过高。
所以,在进一步挖掘之后,我发现了问题所在。 This page 通过解释有关空闲和保持活动超时的一些细节,有助于解开谜团:
There are two immediate causes for receiving a 504 from an ELB:
- The application actually took longer than the ELB's connection timeout to respond. This is a slow timeout — the 504 will typically be
returned after a number of seconds, with the default for an ELB being
60 seconds. In this case, it is necessary either to increase the ELB's
connection timeout, or improve application performance.
- The application did not respond to the ELB at all, instead closing its connection when data was requested. This is a fast timeout — the
504 will typically be returned in a matter of milliseconds, well under
the ELB's timeout setting.
第一种情况是我所见并通过提高 ELB 超时解决的。第二种情况描述了我在提高 ELB 超时后看到的令人困惑的行为。我的日志文件具有“-1 -1 -1”模式,就像文章中的示例日志一样:
2015-12-11T13:42:07.736195Z my-elb 10.0.0.1:59893 - -1 -1 -1 504 0 0 0 "GET http://my-elb/ HTTP/1.1" "curl/7.19.7" - -
由此得出结论:
In short, an ELB's connection timeout must be set lower than both the
application's idle and keepalive timeouts to prevent spurious 504s
from being generated.
在开始使用 ELB 之前的开发过程中,我设置了 Tomcat 超时,使其恰好高于默认的 ELB 超时。当我提高 ELB 超时时,我使它高于我在 Tomcat 中设置的 connectionTimeout
。将 connectionTimeout
提高到略高于我的新 ELB 超时值,消除了神秘的 504 错误。所以,我现在已经摆脱了 "slow" 和 "fast" 超时错误。
Tomcat 也有一个 keepAliveTimeout
设置,如果没有设置,默认与 connectionTimeout
相同。我没有设置它,所以修改 connectionTimeout
足以解决我的问题。
我在多个 EC2 实例上有一个应用程序 运行,由 Apache Tomcat 提供服务。我在应用程序前面设置了一个 AWS Elastic Load Balancer,一切基本上都按预期工作。但是,我偶尔会从 ELB 收到随机的 504 超时错误。这似乎与负载无关,因为我看到了轻负载和重负载下的错误。此外,它似乎不会在任何常规模式或情况下发生。
在我早些时候的测试中,我遇到了 504 错误,因为我的应用程序响应时间比 ELB 上默认的 60 秒超时时间长。我通过将 ELB 超时提高到我的应用程序所需的级别来解决这个问题。但是,我现在遇到的 504 错误发生得非常快。因此,例如,我看到的一个错误是关于响应时间约为一秒的请求。当请求不可能在应用程序服务器上超时时出现超时错误似乎很奇怪。
这可能是一个与 this question 类似的问题,尽管我无法从提供的信息中完全分辨出来。另外,我没有额外的负载均衡器,只是 ELB 直接到 Tomcat.
ELB 不太可能是问题的原因,而是表明您有问题。 504 错误是 Gateway Timeout,当服务器(在本例中 Tomcat)响应不够快时发生。
(我多年来一直将 ELB 用于极高负载服务,并且不同意 link 对其他 SO 答案的回答。虽然这在技术上是正确的,并且可能是正确的非常高爆率,一秒上千个请求,除非你的量这么大,我先看看你的申请。)
确认它不是 ELB 的最明显测试是直接针对集群中的 Tomcat 服务器之一测试请求。如果您无法路由到 Tomcat 个实例,您可以尝试从您要测试的实例 curl
到本地主机。
另请注意,ELB 有一个健康检查设置,这些设置允许您设置某些规则来定义服务器是否健康——如果不健康,ELB 将从集群中删除它,直到它再次健康。健康可以包括及时的反应。查看ELB的CloudWatch,看看最近有没有不健康的实例。
如果您在开发中看到 504,而现在它更频繁了,我猜这实际上是一个负载或性能问题。最典型的是 Java 由于底层应用程序的问题而陷入一些垃圾收集抖动问题。查看您的 EC2 实例的 CloudWatch 指标,了解内存或 CPU 是否过高或过高。
所以,在进一步挖掘之后,我发现了问题所在。 This page 通过解释有关空闲和保持活动超时的一些细节,有助于解开谜团:
There are two immediate causes for receiving a 504 from an ELB:
- The application actually took longer than the ELB's connection timeout to respond. This is a slow timeout — the 504 will typically be returned after a number of seconds, with the default for an ELB being 60 seconds. In this case, it is necessary either to increase the ELB's connection timeout, or improve application performance.
- The application did not respond to the ELB at all, instead closing its connection when data was requested. This is a fast timeout — the 504 will typically be returned in a matter of milliseconds, well under the ELB's timeout setting.
第一种情况是我所见并通过提高 ELB 超时解决的。第二种情况描述了我在提高 ELB 超时后看到的令人困惑的行为。我的日志文件具有“-1 -1 -1”模式,就像文章中的示例日志一样:
2015-12-11T13:42:07.736195Z my-elb 10.0.0.1:59893 - -1 -1 -1 504 0 0 0 "GET http://my-elb/ HTTP/1.1" "curl/7.19.7" - -
由此得出结论:
In short, an ELB's connection timeout must be set lower than both the application's idle and keepalive timeouts to prevent spurious 504s from being generated.
在开始使用 ELB 之前的开发过程中,我设置了 Tomcat 超时,使其恰好高于默认的 ELB 超时。当我提高 ELB 超时时,我使它高于我在 Tomcat 中设置的 connectionTimeout
。将 connectionTimeout
提高到略高于我的新 ELB 超时值,消除了神秘的 504 错误。所以,我现在已经摆脱了 "slow" 和 "fast" 超时错误。
Tomcat 也有一个 keepAliveTimeout
设置,如果没有设置,默认与 connectionTimeout
相同。我没有设置它,所以修改 connectionTimeout
足以解决我的问题。