504 Gateway Timeout

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

问题

客户端应用收到 HTTP 状态代码 504 和消息 Gateway Timeout,作为 API 调用的响应。

HTTP 状态代码 - 504 Gateway Timeout 错误表示客户端在 API 执行期间未及时收到来自边缘网关或后端服务器的响应

错误消息

客户端应用会获得以下响应代码:

HTTP/1.1 504 Gateway Timeout

在某些情况下,可能还会看到以下错误消息:

{
   "fault": {
      "faultstring": "Gateway Timeout",
      "detail": {
           "errorcode": "messaging.adaptors.http.flow.GatewayTimeout"
       }
    }
}

导致网关超时的原因是什么?

通过边缘平台发出 API 请求的典型路径为客户端 -> 路由器 -> 消息处理器 -> 后端服务器,如下图所示:

Edge 平台中的客户端应用、路由器和消息处理器均设置了合适的超时值。Edge 平台会按照超时值,在特定的时间段内为每个 API 请求发送响应。如果您未在指定的时间段内收到响应,系统便会返回 504 Gateway Timeout Error

下表详细说明了 Edge 中何时可能会出现超时:

发生超时情况 具体说明
消息处理器发生超时
  • 后端服务器在消息处理器上的指定超时期限内未响应消息处理器。
  • 消息处理器超时,并将响应状态作为 504 Gateway Timeout 发送到路由器。
路由器超时
  • 消息处理器在路由器上的指定超时期限内未响应路由器。
  • 路由器超时,并将响应状态作为 504 Gateway Timeout 发送到客户端应用。
客户端应用超时
  • 路由器在路由器上的指定超时期限内未响应客户端应用。
  • 客户端应用超时,结束对最终用户的响应状态 (504 Gateway Timeout)。

可能的原因

在 Edge 中,导致 504 Gateway Timeout 错误的典型原因如下:

原因 具体说明 针对以下项目提供的步数:
后端服务器速度缓慢 处理 API 请求的后端服务器由于负载过高或性能不佳而过慢。 公有云和私有云用户
Edge 导致 API 请求处理速度缓慢 由于负载较高或性能不佳,Edge 需要很长时间来处理 API 请求。

后端服务器速度缓慢

如果后端服务器速度很慢或需要很长时间来处理 API 请求,您会收到 504 Gateway Timeout 错误。如上一部分所述,在以下任一情况下都可能会出现超时:

  1. 消息处理器在后端服务器响应前超时。
  2. 路由器在消息处理器/后端服务器响应前超时。
  3. 客户端应用在路由器/消息处理器/后端服务器响应之前超时。

以下部分介绍了如何在上述每种情况下诊断和解决问题。

场景 1 消息处理器在后端服务器响应之前超时

诊断

您可以使用以下过程诊断是否因后端服务器速度缓慢而发生了 504 Gateway Timeout 错误。

过程 1 使用跟踪

如果问题仍然存在(504 错误仍然存在),请按以下步骤操作:

  1. 在 Edge 界面中跟踪受影响的 API。请等待错误发生,或者进行 API 调用,然后进行一些 API 调用并重现 504 Gateway Timeout 错误。
  2. 出现错误后,请检查响应代码显示为 504 的具体请求。
  3. 检查每个阶段所用时间,并记下花费最多时间的阶段。
  4. 如果您在以下某个阶段之后立即观察到用时最长的错误,则表示后端服务器速度缓慢或处理请求需要很长时间:
    • 请求已发送到目标服务器
    • ServiceCallout 政策

以下代码提供了一个示例跟踪记录,其显示后端服务器在 55 秒后仍未响应,从而导致 504 Gateway Timeout 错误:

在上述跟踪记录中,由于后端服务器未响应,消息处理器在 55002 毫秒后超时。

过程 #2 使用消息处理器日志

  1. 检查消息处理器的日志 (/opt/apigee/var/log/edge-message-processor/logs/system.log)
  2. 如果您在特定时间发现特定 API 代理请求的 Gateway TimeoutonTimeoutRead 错误,则表示消息处理器已超时。

    显示网关超时错误的消息处理器日志示例

    2015-09-29 20:16:54,340 org:myorg env:staging api:profiles rev:13 NIOThread@1
    ERROR ADAPTORS.HTTP.FLOW - AbstractResponseListener.onException() :
    AbstractResponseListener.onError(HTTPResponse@4d898cf1, Gateway
    Timeout)
    2015-09-29 20:16:57,361 org:myorg env:staging api:profileNewsletters rev:8
    NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context$3.onTimeout() :
    SSLClientChannel[C:XX.XX.XX.XX:443 Remote
    host:192.168.38.54:38302]@120171 useCount=2 bytesRead=0
    bytesWritten=824 age=55458ms lastIO=55000ms .onTimeoutRead
    

    在上面的消息处理器日志中,您注意到以 IP 地址 XX.XX.XX.XX 表示的后端服务器在 55 秒 (lastIO=55000ms) 后仍未响应。因此,消息处理器超时并发送了 504 Gateway Timeout 错误。

    勾选:消息处理器上的超时是如何控制的?

    • 消息处理器上的超时控制方式。(通常通过属性 HTTPTransport.io.timeout.millis 设置消息处理器,默认超时值为 55 秒)。此超时值适用于此消息处理器所服务组织的所有 API 代理。
      • 如果后端服务器在 55 秒内没有响应,则消息处理器会超时,并向客户端发送 504 Gateway Timeout 错误。
    • 消息处理器中指定的超时值可以由 API 代理中指定的属性 io.timeout.millis 替换。此超时值适用于指定了上述属性的特定 API 代理。例如,如果在 API 代理中将 io.timeout.millis 设置为 10 秒,则系统将为此特定 API 代理使用 10 秒的超时值。
      • 如果后端服务器在 10 秒内没有针对特定 API 代理做出响应,则消息处理器会超时并向客户端发送 504 Gateway Timeout 错误。

分辨率

  1. 检查后端服务器时间超过 55 秒的原因,看看是否可以对其进行修复/优化以加快响应速度。
  2. 如果无法修复/优化后端服务器,或者已知后端服务器花费的时间超过配置的超时时间,请 将路由器和消息处理器上的超时值增加到一个合适的值。

场景 2 - 在消息处理器/后端服务器响应之前路由器超时

如果路由器在消息处理器/后端服务器响应之前超时,您可能会收到 504 Gateway Timeout 错误。在下列任一情况下,都可能会发生这种情况:

  • 在路由器上设置的超时值小于在消息处理器上设置的超时值。例如,假设路由器上的超时时间为 50 秒,而消息处理器上的超时时间为 55 秒。
    路由器超时 消息处理器超时
    50 秒 55 秒
  • 使用 API 代理的目标端点配置中设置的 io.timeout.millis 属性,将消息处理器上的超时值替换为更高的超时值:

    例如,如果设置了以下超时值:

    路由器超时 消息处理器超时 API 代理内的超时时间
    57 秒 55 秒 120 秒

    io.timeout.millis 在 API 代理中设置为 120 秒:

    <HTTPTargetConnection>
         <Properties>
              <Property name="io.timeout.millis">120000</Property>
          </Properties>
          <URL>http://www.apigee.com</URL>
    </HTTPTargetConnection>
    

    然后,即使消息处理器的超时值(55 秒)小于路由器上的超时值(57 秒),消息处理器也不会在 55 秒后超时。这是因为消息处理器上 55 秒的超时值会被 API 代理中设置的 120 秒值替换。因此,此特定 API 代理的消息处理器的超时值为 120 秒。

    由于路由器的超时值(57 秒)低于 API 代理中设置的 120 秒,因此如果后端服务器在 57 秒后未响应,路由器将超时。

诊断

  1. 查看 NGINX 访问日志 (/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log)
  2. 如果路由器在消息处理器之前超时,您将在特定 API 请求的 NGINX 访问日志中看到 504 状态,并且来自消息处理器的 message id 将设置为 -。这是因为路由器在路由器上设置的超时期限内未收到消息处理器的任何响应。

    由于路由器超时而导致 504 错误的 NGINX 日志条目示例

  3. 请注意上面的示例中,请注意 NGINX 上的 504 状态,消息处理器中的消息 ID 为 -,总耗时为 57.001 秒。这是因为路由器在 57.001 秒后超时,我们未收到消息处理器的任何响应。
  4. 在这种情况下,您会在消息处理器日志中看到 Broken Pipe 异常 (/opt/apigee/var/log/edge-message-processor/logs/system.log).
    2017-06-09 00:00:25,886 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-mp01-18869-23151-1  NIOThread@1 INFO  HTTP.SERVICE - ExceptionHandler.handleException() : Exception java.io.IOException: Broken pipe occurred while writing to channel ClientOutputChannel(ClientChannel[A:XX.XX.XX.XX:8998 Remote host:YY.YY.YY.YY:51400]@23751 useCount=1 bytesRead=0 bytesWritten=486 age=330465ms  lastIO=0ms )
    2017-06-09 00:00:25,887  org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-mp01-18869-23151-1  NIOThread@1 INFO  HTTP.SERVICE - ExceptionHandler.handleException() : Exception trace:
    java.io.IOException: Broken pipe
            at com.apigee.nio.channels.ClientOutputChannel.writePending(ClientOutputChannel.java:51) ~[nio-1.0.0.jar:na]
            at com.apigee.nio.channels.OutputChannel.onWrite(OutputChannel.java:116) ~[nio-1.0.0.jar:na]
            at com.apigee.nio.channels.OutputChannel.write(OutputChannel.java:81) ~[nio-1.0.0.jar:na]
             … <snipped>
    

显示此错误是因为路由器超时后,会关闭与消息处理器的连接。当消息处理器完成处理时,它会尝试将响应写入路由器。由于与路由器的连接已关闭,因此您会在消息处理器上获得 Broken Pipe exception

在上述情况下,会出现这种异常。因此,504 Gateway Timeout 错误的实际原因仍然是后端服务器需要较长的响应时间,您需要解决该问题。

分辨率

  1. 如果是自定义后端服务器,则:
    1. 检查后端服务器为何需要很长时间进行响应,看看能否通过修复/优化来加快响应速度。
    2. 如果无法修复/优化后端服务器,或者已知后端服务器需要很长时间,请增加路由器和消息处理器上的超时值

      提示:按以下顺序为不同组件设置超时值:

      客户端超时 > 路由器超时 > 消息处理器超时 > API 代理内超时

  2. 如果是 NodeJS 后端服务器,则:
    1. 检查 NodeJS 代码是否调用任何其他后端服务器,以及返回响应是否花费了很长时间。请检查后端服务器花费的时间较长的原因,并酌情解决此问题。
    2. 检查消息处理器是否出现了高 CPU 或内存使用率:
      1. 如果任何消息处理器的 CPU 使用率过高,则使用以下命令每 30 秒生成三次线程转储
        JAVA_HOME/bin/jstack -l PID > FILENAME
      2. 如果任何消息处理器的内存用量较高,请使用以下命令生成堆转储
        sudo -u apigee JAVA_HOME/bin/jmap -dump:live,format=b,file=FILENAME PID
      3. 使用以下命令重启消息处理器。这会降低 CPU 和内存:
        /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
      4. 监控 API 调用以确认问题是否仍然存在。
      5. 联系 Apigee Edge 支持团队,并提供线程转储、堆转储和消息处理器日志(/opt/apigee/var/log/edge-message-processor/logs/system.log)可帮助调查 CPU/内存用量高的原因。

勾选:如何控制消息处理器上的 NodeJS 后端服务器的超时

  • NodeJS 后端服务器在消息处理器的 JVM 进程中运行。NodeJS 后端服务器的超时值通过 nodejs.properties 文件中的 http.request.timeout.seconds 属性进行控制。此属性默认设置为 0,也就是说,对于属于此消息处理器所服务组织的所有 API 代理,超时默认处于停用状态。因此,即使 NodeJS 后端服务器需要很长时间,消息处理器也不会超时。
  • 但是,如果 NodeJS 后端服务器花费的时间较长,并且 API 请求花费的时间超过 57 秒,那么路由器将超时,并向客户端发送 504 Gateway Timeout 错误。

场景 3 - 在路由器/消息处理器/后端服务器响应之前,客户端应用超时

如果客户端应用在后端服务器响应之前超时,您可能会收到 504 Gateway Timeout 错误。如果出现以下情况,则可能会出现上述情况:

  1. 在客户端应用上设置的超时值低于在路由器和消息处理器上设置的超时值:

    例如,如果设置了以下超时值:

    客户端超时 路由器超时 消息处理器超时
    50 秒 57 秒 55 秒

    在这种情况下,可以通过 Edge 获得 API 请求的响应的总时间不超过 50 秒。这包括发出 API 请求所用的时间、边缘(路由器、消息处理器)处理请求、发送到后端服务器的请求(如果适用)、后端处理请求并发送响应、边缘处理响应并最终将其发送回客户端。

    如果路由器在 50 秒内未响应客户端,则客户端将超时并关闭与路由器的连接。客户端将获得 504 的响应代码。

    这会使 NGINX 设置状态代码 499,表明客户端已关闭连接。

诊断

  1. 如果客户端应用在收到来自路由器的响应之前超时,则会关闭与路由器的连接。在这种情况下,您会在特定 API 请求的 NGINX 访问日志中看到状态代码 499。

    显示状态代码 499 的 NGINX 日志条目示例

  2. 请注意,在上面的示例中,NGINX 上的 499 状态和已用总时间为 50.001 秒。这表示客户端在 50.001 秒后超时。
  3. 在这种情况下,您会在消息处理器日志中看到 Broken Pipe 异常 (/opt/apigee/var/log/edge-message-processor/logs/system.log).
    2017-06-09 00:00:25,886 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-1-11193-11467656-1  NIOThread@1 INFO  HTTP.SERVICE - ExceptionHandler.handleException() : Exception java.io.IOException: Broken pipe occurred while writing to channel ClientOutputChannel(ClientChannel[A:XX.XX.XX.XX:8998 Remote host:YY.YY.YY.YY:51400]@23751 useCount=1 bytesRead=0 bytesWritten=486 age=330465ms  lastIO=0ms )
    2017-06-09 00:00:25,887  org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-1-11193-11467656-1  NIOThread@1 INFO  HTTP.SERVICE - ExceptionHandler.handleException() : Exception trace:
    java.io.IOException: Broken pipe
            at com.apigee.nio.channels.ClientOutputChannel.writePending(ClientOutputChannel.java:51) ~[nio-1.0.0.jar:na]
            at com.apigee.nio.channels.OutputChannel.onWrite(OutputChannel.java:116) ~[nio-1.0.0.jar:na]
            at com.apigee.nio.channels.OutputChannel.write(OutputChannel.java:81) ~[nio-1.0.0.jar:na]
             … <snipped>
    
    
  4. 路由器超时后,会关闭与消息处理器的连接。当消息处理器完成处理时,它会尝试将响应写入路由器。由于与路由器的连接已关闭,因此您会在消息处理器上获得 Broken Pipe exception
  5. 在上述情况下,这种例外情况属于正常现象。因此,504 Gateway Timeout 错误的实际原因仍然是后端服务器需要很长时间进行响应,您需要解决该问题。

分辨率

  1. 如果您的自定义后端服务器,则:
    1. 检查后端服务器,确定为什么超过 57 秒,看看是否可以对其进行修复/优化以加快响应速度。
    2. 如果无法修复/优化后端服务器,或者如果您知道后端服务器需要很长时间,请增加路由器和消息处理器上的超时值

      提示:按以下顺序为不同组件设置超时值:

      客户端超时 > 路由器超时 > 消息处理器超时 > API 代理内超时

  2. 如果是 NodeJS 后端,则:
    1. 检查 NodeJS 代码是否调用任何其他后端服务器,以及是否需要很长时间返回。查看这些后端服务器花费的时间较长的原因。
    2. 检查消息处理器是否出现了高 CPU 或内存使用率:
      1. 如果消息处理器的 CPU 使用率过高,则使用以下命令每 30 秒生成三次线程转储
        JAVA_HOME/bin/jstack -l PID > FILENAME
      2. 如果消息处理器的内存用量较高,请使用以下命令生成堆转储
        sudo -u apigee JAVA_HOME/bin/jmap -dump:live,format=b,file=FILENAME PID
      3. 使用以下命令重启消息处理器。这样应该会降低 CPU 和内存:
        /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
      4. 监控 API 调用以确认问题是否仍然存在。
      5. 联系 Apigee Edge 支持团队,并提供线程转储、堆转储和消息处理器日志(/opt/apigee/var/log/edge-message-processor/logs/system.log)帮助他们调查 CPU/内存用量过高的原因。

增加路由器和消息处理器上的超时值

根据您的要求,谨慎选择要在路由器和消息处理器上设置的超时值。请勿设置任意大的超时值。如果您需要帮助,请与 Apigee Edge 支持团队联系。

路由器

chown apigee:apigee /opt/apigee/customer/application/router.properties
  1. 如果路由器机器上还没有 /opt/apigee/customer/application/router.properties 文件,请创建一个。
  2. 将以下代码行添加到此文件中:
    conf_load_balancing_load.balancing.driver.proxy.read.timeout=TIME_IN_SECONDS

    例如,如果要将超时值设置为 120 秒,请按如下方式设置:

    conf_load_balancing_load.balancing.driver.proxy.read.timeout=120
  3. 确保此文件归 Apigee 所有:
  4. 重启路由器:
    /opt/apigee/apigee-service/bin/apigee-service edge-router restart
    
  5. 如果您有多个路由器,请在所有路由器上重复上述步骤。

消息处理器

  1. 在消息处理器机器上创建 /opt/apigee/customer/application/message-processor.properties 文件(如果该文件尚不存在)。
  2. 将以下代码行添加到此文件中:
    conf_http_HTTPTransport.io.timeout.millis=TIME_IN_MILLISECONDS

    例如,如果要将超时值设置为 120 秒,请按如下方式设置:

    conf_http_HTTPTransport.io.timeout.millis=120000
  3. 确保此文件归 Apigee 所有:
    chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
  4. 重启消息处理器:
    /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
  5. 如果您有多个消息处理器,请对所有消息处理器重复上述步骤。

提示:按以下顺序为不同组件设置超时值:

客户端超时 > 路由器超时 > 消息处理器超时 > API 代理内超时

Edge 导致 API 请求处理速度缓慢

如果 Edge 运行速度非常慢并且/或处理 API 请求需要很长时间,那么您会收到 504 Gateway Timeout 错误。

诊断

  1. 在 Edge 界面中跟踪受影响的 API。
  2. 请等待错误发生,或者进行 API 调用,然后进行一些 API 调用并重现 504 Gateway Timeout 错误。
  3. 请注意,在这种情况下,您可能会在 Trace 中看到成功响应。
    1. 路由器/客户端超时,因为消息处理器未在路由器/客户端上的指定超时期限(以最短超时期限为准)做出响应。但是,消息处理器会继续处理请求,并且可能会成功完成。
    2. 此外,仅当消息处理器与 HTTP/HTTPS 后端服务器通信时,才会触发在消息处理器上设置的 HTTPTransport.io.timeout.millis 值。换句话说,如果 API 代理中的任何政策(ServiceCallout 政策除外)都用了很长时间,则不会触发此超时。
  4. 出错后,请检查所用时间最长的特定请求
  5. 检查每个阶段所用的时间,并记下使用时间最长的阶段。
  6. 如果您观察到除服务调用程序政策以外的任何其他政策中经过的时间最长,则表示 Edge 处理请求花了很长时间。
  7. 下面是一个示例界面跟踪记录,显示了 JavaScript 政策上经过的时间非常长:

  8. 在上面的示例中,您注意到 JavaScript 政策花费的时间非常长,约为 245 秒。

分辨率

  1. 检查响应时间过长的政策,以及是否有任何可能需要很长时间来处理的自定义代码。如果存在任何此类代码,请查看您能否修复/优化识别出的代码。
  2. 如果没有可能导致处理时间较长的自定义代码,请检查消息处理器是否出现了高 CPU 或内存使用率:
    1. 如果任何消息处理器的 CPU 使用率过高,则使用以下命令每 30 秒生成三次线程转储
      JAVA_HOME/bin/jstack -l PID > FILENAME
    2. 如果任何消息处理器的内存用量较高,请使用以下命令生成堆转储
      sudo -u apigee JAVA_HOME/bin/jmap -dump:live,format=b,file=FILENAME PID
    3. 使用以下命令重启消息处理器。这样做会降低 CPU 和内存。
      /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
    4. 监控 API 调用并确认问题是否仍然存在。
    5. 联系 Apigee Edge 支持团队,并提供线程转储、堆转储和消息处理器日志(/opt/apigee/var/log/edge-message-processor/logs/system.log),帮助他们调查 CPU/内存用量高的原因。

使用 API Monitoring 诊断问题

借助 API 监控功能,您可以快速隔离有问题的方面,从而诊断错误、性能和延迟问题及其来源,例如开发者应用、API 代理、后端目标或 API 平台。

通过一个示例场景演示了如何使用 API Monitoring 排查 API 的 5xx 问题。 例如,您可能希望设置一个提醒,以便在 504 状态代码的数量超过特定阈值时收到通知。