504 Gateway Timeout

您正在查看 Apigee Edge 文档。
前往 Apigee X 文档
信息

问题

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

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

错误消息

客户端应用会收到以下响应代码:

HTTP/1.1 504 Gateway Timeout

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

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

网关超时的原因是什么?

通过 Edge 平台发出的 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:使用 Trace

如果问题仍未解决(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 秒,则 10 秒的超时值将用于此特定 API 代理。
      • 如果后端服务器未在 10 秒内针对特定 API 代理做出响应,则消息处理器会超时并向客户端发送 504 Gateway Timeout 错误。

分辨率

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

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

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

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

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

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

    但是,在 API 代理中,io.timeout.millis 设置为 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 请求所需的时间、Edge(路由器、消息处理器)处理请求的时间、请求发送到后端服务器(如果适用)的时间、后端处理请求并发送响应的时间、Edge 处理响应并最终将其发回给客户端的时间。

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

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

诊断

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

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

  2. 请注意,在上面的示例中,NGINX 上的 499 状态和总耗时为 50.001 秒。这表示客户端在 50.001 秒后超时。
  3. 在这种情况下,您会在消息处理器日志 (/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>
    
    
    ) 中看到 Broken Pipe 异常
  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. 请注意,在这种情况下,您可能会在轨迹中看到成功响应。
    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 监控功能诊断问题

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

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