

# HTTP 504 状态代码 (Gateway Timeout)
<a name="http-504-gateway-timeout"></a>

HTTP 504 状态代码（网关超时）指示当 CloudFront 将请求转发至源后（因为请求的对象不在边缘缓存中），发生了以下情况之一：
+ 源将 HTTP 504 状态代码返回到 CloudFront。
+ 源在请求过期前未响应。

如果流量被防火墙或安全组阻止进入源，或者无法在 Internet 上访问源，CloudFront 将返回 HTTP 504 状态代码。请首先检查是否存在这些问题。然后，如果访问没有问题，请探究应用程序延迟和服务器超时，以帮助您确定并解决问题。

**Topics**
+ [将您的源服务器上的防火墙设置为允许 CloudFront 流量](#http-504-gateway-timeout-configure-firewall)
+ [将您的源服务器上的安全组设置为允许 CloudFront 流量](#http-504-gateway-timeout-configure-security-groups)
+ [使自定义源服务器在 Internet 上可访问](#http-504-gateway-timeout-make-origin-accessible)
+ [查找并修复源服务器上来自应用程序的延迟响应](#http-504-gateway-timeout-slow-application)

## 将您的源服务器上的防火墙设置为允许 CloudFront 流量
<a name="http-504-gateway-timeout-configure-firewall"></a>

如果您的源服务器上的防火墙阻止 CloudFront 流量，CloudFront 将返回 HTTP 504 状态代码，所以在检查其他问题之前，务必确保不是这个问题的原因。

您用于确定这是否是与您的防火墙相关的问题的方法取决于源服务器使用的系统：
+ 如果您使用的是 Linux 服务器上的 IPTable 防火墙，则可以搜索帮助您使用 IPTable 的工具和信息。
+ 如果您使用的是 Windows 服务器上的 Windows 防火墙，请参阅 Microsoft 文档中的[添加或编辑防火墙规则](https://technet.microsoft.com/en-us/library/cc753558(v=ws.11).aspx)。

当您评估源服务器上的防火墙配置时，基于发布的 IP 地址范围查找阻止来自 CloudFront 边缘站点的流量的任何防火墙或安全规则。有关更多信息，请参阅 [CloudFront 边缘服务器的位置和 IP 地址范围](LocationsOfEdgeServers.md)。

如果 CloudFront IP 地址范围已允许连接至您的源服务器，请确保更新您的服务器的安全规则以合并更改。您可以订阅 Amazon SNS 主题并且在更新 IP 地址范围文件时接收通知。收到该通知后，您可以使用代码检索该文件、解析文件并根据您的当地环境做出相应调整。有关更多信息，请参阅 AWS 新闻博客上的[通过 Amazon SNS 订阅 AWS 公共 IP 地址范围](https://aws.amazon.com/blogs/aws/subscribe-to-aws-public-ip-address-changes-via-amazon-sns/)。

## 将您的源服务器上的安全组设置为允许 CloudFront 流量
<a name="http-504-gateway-timeout-configure-security-groups"></a>

如果您的源使用 Elastic Load Balancing，请检查 [ELB 安全组](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html)并确保安全组允许来自 CloudFront 的入站流量。

您还可以使用 AWS Lambda 自动更新您的安全组，以允许来自 CloudFront 的入站流量。

## 使自定义源服务器在 Internet 上可访问
<a name="http-504-gateway-timeout-make-origin-accessible"></a>

如果 CloudFront 由于自定义源服务器未在 Internet 上公开而无法对其进行访问，CloudFront 将返回 HTTP 504 错误。

CloudFront 边缘站点通过 Internet 连接到源服务器。如果自定义源位于私有网络上，CloudFront 则无法访问它。因此，您无法使用私有服务器（包括[内部经典负载均衡器](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-internal-load-balancers.html)）作为 CloudFront 的源服务器。

要检查互联网流量是否可以连接到原始服务器，请运行以下命令（其中 *OriginDomainName* 是您的服务器的域名）：

对于 HTTPS 流量：
+ nc -zv *OriginDomainName* 443
+ telnet *OriginDomainName* 443

对于 HTTP 流量：
+ nc -zv *OriginDomainName* 80
+ telnet *OriginDomainName* 80

## 查找并修复源服务器上来自应用程序的延迟响应
<a name="http-504-gateway-timeout-slow-application"></a>

服务器超时通常是应用程序响应时间过长或超时值设置得过低的结果。

帮助避免 HTTP 504 错误的快速解决方法是为您的分配设置一个较高的 CloudFront 超时值。但是，建议您首先确保解决与应用程序和源服务器相关的任何性能和延迟问题。然后，您可以设置一个合理的超时值，以帮助防止 HTTP 504 错误并向用户提供良好的响应能力。

以下是您要查找性能问题并进行更正可以采取的步骤的概述：

1. 测量您的 Web 应用程序的典型和高负载延迟 (响应能力)。

1. 添加其他资源，如 CPU 或内存 (如果需要)。采取解决问题的其他步骤，如优化数据库查询以适应高负载场景。

1. 如果需要，调整您的 CloudFront 分配的超时值。

以下是关于每个步骤的详细信息。

### 测量典型和高负载延迟
<a name="http-504-gateway-timeout-slow-application-measure-latency"></a>

要确定一个或多个后端 Web 应用程序服务器是否遇到高延迟，请在每个服务器上运行以下 Linux curl 命令：

```
curl -w "DNS Lookup Time: %{time_namelookup} \nConnect time: %{time_connect} \nTLS Setup: %{time_appconnect} \nRedirect Time: %{time_redirect} \nTime to first byte: %{time_starttransfer} \nTotal time: %{time_total} \n" -o /dev/null https://www.example.com/yourobject
```

**注意**  
如果您在服务器上运行的是 Windows，则可以搜索并下载用于 Windows 运行类似命令的 curl。

您在测量并评估在您的服务器上运行的应用程序的延迟时，请注意以下事项：
+ 延迟值是相对于每个应用程序的。但是，合理的做法是第一个字节的时间采用毫秒而不是秒或更大的单位。
+ 如果您在正常负载下测量应用程序延迟且结果正常，请注意查看器在高负载下可能仍会遇到超时。当存在高需求时，服务器可能已延迟响应或根本未响应。为了帮助防止高负载延迟问题，请检查您的服务器的资源，如 CPU、内存和磁盘读写情况，以确保您的服务器具有针对高负载进行扩展的容量。

  您可以运行以下 Linux 命令来检查 Apache 进程所使用的内存：

  `watch -n 1 "echo -n 'Apache Processes: ' && ps -C apache2 --no-headers | wc -l && free -m"`
+ 服务器上的 CPU 使用率高可能会大幅降低应用程序的性能。如果您对后端服务器使用的是 Amazon EC2 实例，请检查服务器的 CloudWatch 指标以查看 CPU 利用率。有关更多信息，请参阅 [Amazon CloudWatch 用户指南](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)。或者，如果您使用的是自己的服务器，请参阅服务器帮助文档来了解有关如何检查 CPU 利用率的说明。
+ 检查在高负载下是否存在其他潜在问题，如存在大量请求时数据库查询运行缓慢。

### 添加资源并优化服务器和数据库
<a name="http-504-gateway-timeout-slow-application-add-resources"></a>

在您评估应用程序和服务器的响应能力后，请确保您有用于典型流量和高负载情况的足够资源：
+ 如果您有自己的服务器，请确保它具有足够的 CPU、内存和磁盘空间来处理查看器请求 (根据您的评估)。
+ 如果使用 Amazon EC2 实例作为后端服务器，请确保实例类型具有适当的资源来满足传入请求。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[实例类型](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)。

此外，请考虑以下帮助避免超时的优化步骤：
+ 如果 curl 命令返回的第一个字节的时间值似乎很高，请采取改进您的应用程序性能的步骤。提高应用程序响应能力反过来将有助于减少超时错误。
+ 优化数据库查询以确保它们可以处理大量请求，而不会降低性能。
+ 在您的后端服务器上设置[保持连接 (持久性)](https://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01) 连接。该选项有助于避免在必须为后续请求或用户重新建立连接时发生的延迟。
+ **如果您使用弹性负载均衡作为源**，则导致 504 错误的可能原因如下：
  + 负载均衡器未能在连接超时到期（10 秒）之前建立与目标的连接。
  + 负载均衡器与目标建立了连接，但目标在空闲超时周期到期之前未响应。
  + 子网的网络访问控制列表（ACL）不允许在临时端口（1024-65535）上存在从目标到负载均衡器节点的流量。
  + 目标返回的 content-length 标头大于整个正文。负载均衡器因等待缺少的字节而超时。
  + 目标是 Lambda 函数，而 Lambda 在连接超时过期之前没有响应。

  有关减少延迟的更多信息，请参阅[如何对 ELB 经典负载均衡器上的高延迟进行故障排除？](https://repost.aws/knowledge-center/elb-latency-troubleshooting)
+ **如果您使用 MediaTailor 作为源**，则导致 504 错误的可能原因如下：
  + 如果相对 URL 处理不当，MediaTailor 可能会从播放器收到格式错误的 URL。
  + 如果 MediaPackage 是 MediaTailor 的清单来源，那么 MediaPackage 404 清单错误可能导致 MediaTailor 返回 504 错误。
  + 向 MediaTailor 原始服务器发出的请求需要 2 秒以上的时间才能完成。
+ **如果您使用 Amazon API Gateway 作为源**，则导致 504 错误的可能原因如下：
  + 集成请求所花的时间比 API Gateway REST API 最大集成超时参数更长。有关更多信息，请参阅[如何使用 API Gateway 解决 API HTTP 504 超时错误？](https://repost.aws/knowledge-center/api-gateway-504-errors)

### 如果需要，请调整 CloudFront 超时值
<a name="http-504-gateway-timeout-slow-application-adjust-timeout"></a>

如果您已评估并解决低应用程序性能、源服务器容量及其他问题，但查看器仍遇到 HTTP 504 错误，则您应考虑更改在您的分配中为源响应超时指定的时间。有关更多信息，请参阅 [响应超时](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout)。