使用 Tomcat 的 Elastic Load Balancer 出现 504 错误

Posted

技术标签:

【中文标题】使用 Tomcat 的 Elastic Load Balancer 出现 504 错误【英文标题】:504 errors from Elastic Load Balancer using Tomcat 【发布时间】:2018-06-14 15:21:07 【问题描述】:

我有一个在多个 EC2 实例上运行并由 Apache Tomcat 提供服务的应用程序。我在应用程序前面设置了一个 AWS Elastic Load Balancer,一切基本上都按预期工作。但是,我偶尔会从 ELB 收到一个随机的 504 超时错误。这似乎与负载无关,因为我已经看到轻负载和重负载下的错误。此外,它似乎不会在任何常规模式或情况下发生。

在我的测试早期,我收到了 504 错误,因为我的应用程序响应时间比 ELB 上默认的 60 秒超时时间要长。我通过将 ELB 超时提高到我的应用程序所需的级别来解决这个问题。但是,我现在遇到的 504 错误发生得非常快。因此,例如,我看到的一个错误是响应时间约为一秒的请求。当应用程序服务器上的请求不可能超时时,出现超时错误似乎很奇怪。

这可能是与this question 类似的问题,尽管我无法从提供的信息中完全看出。另外,我没有额外的负载均衡器,只有 ELB 直接连接到 Tomcat。

【问题讨论】:

你在记录 ELB 请求吗? 【参考方案1】:

ELB 不太可能是问题的原因,而是表明您有问题。 504 错误是 Gateway Timeout,当服务器(在本例中为 Tomcat)响应不够快时发生。

(多年来,我一直在使用 ELB 进行极高负载的服务,并且不同意其他 SO 答案的链接的答案。虽然这在技术上是正确的,并且可能对 非常正确 em> 高突发率,例如每秒数千个请求,除非您的流量如此之高,否则我会先查看您的应用程序。)

确认它不是 ELB 的最明显测试是直接针对集群中的 Tomcat 服务器之一测试请求。如果您无法路由到 Tomcat 实例,您可以尝试从您要测试的实例将 curl 到 localhost。

还请注意,ELB 有一个健康检查设置,这些设置允许您设置某些规则来定义服务器是否健康——如果不是,ELB 会将其从集群中删除,直到它再次健康为止。健康可以包括及时响应。查看 ELB 的 CloudWatch 以查看最近是否存在不健康的实例。

如果您在开发中看到 504,现在它更频繁了,我猜这实际上是一个负载或性能问题。最典型的是,由于底层应用程序的问题,Java 陷入了一些垃圾收集抖动问题。查看您的 EC2 实例的 CloudWatch 指标,了解内存或 CPU 是高还是高。

【讨论】:

【参考方案2】:

所以,经过进一步挖掘,我发现了问题所在。 This page 通过解释有关空闲和保持活动超时的一些细节,有助于解开谜团:

从 ELB 收到 504 有两个直接原因:

    应用实际响应时间超过了 ELB 的连接超时时间。这是一个缓慢的超时——504 通常是 几秒钟后返回,ELB 的默认值为 60 秒。在这种情况下,有必要增加 ELB 的 连接超时,或提高应用性能。 应用程序根本没有响应 ELB,而是在请求数据时关闭其连接。这是一个快速超时—— 504 通常会在几毫秒内返回,远低于 ELB 的超时设置。

第一种情况是我看到并通过提高 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" - -

从结论:

简而言之,ELB 的连接超时时间必须设置为低于 应用程序的空闲和保持活动超时,以防止虚假 504 从被生成。

在我开始使用 ELB 之前的开发过程中,我设置了 Tomcat 超时,使其恰好高于默认的 ELB 超时。当我提高 ELB 超时时,我使它高于我在 Tomcat 中设置的connectionTimeout。将connectionTimeout 提高到略高于我的新 ELB 超时值,可以消除神秘的 504 错误。所以,我现在已经摆脱了“慢”和“快”超时错误。

Tomcat 还有一个keepAliveTimeout 设置,如果未设置,则默认与connectionTimeout 相同。我没有设置它,所以修改connectionTimeout 足以解决我的问题。

【讨论】:

这里是亚马逊文档的链接:docs.aws.amazon.com/elasticloadbalancing/latest/classic/… 这提到了 ELB 在无法控制关闭与服务器的连接时讨厌的事实。您的服务器必须支持比 ELB 上的空闲超时更长时间的保持活动,并且如果您打算有更长的响应超时,则必须在该时间内提供至少一个 HTTP 100。

以上是关于使用 Tomcat 的 Elastic Load Balancer 出现 504 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何设置我的 Elastic Beanstalk 应用程序以使用 Application Load Balancer?

在 AWS Elastic Load Balancer 后面使用 Primus.io (websockets)

Elastic Load Balancing 非终止 SSL 连接上的代理协议

如何使用 Classic Load Balancer 配置 Elastic Beanstalk NodeJS 应用程序以使用 HTTPS?

非 www 到 www 使用 AWS Elastic Load Balancer 和 Nginx

如何使用 .ebextensions 将 Application Load Balancer 固定响应添加到 AWS Elastic Beanstalk