502 Bad Gateway 意外 EOF

<ph type="x-smartling-placeholder"></ph> 您正在查看 Apigee Edge 文档。
转到 Apigee X 文档
信息

问题

客户端应用将收到 HTTP 状态代码 502 以及消息 Bad Gateway 作为对 API 调用的响应。

HTTP 状态代码 502 表示客户端未收到来自 实际应执行请求的后端服务器

错误消息

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

HTTP/1.1 502 Bad Gateway

此外,您可能还会看到以下错误消息:

{
   "fault": {
      "faultstring": "Unexpected EOF at target",
      "detail": {
           "errorcode": "messaging.adaptors.http.UnexpectedEOFAtTarget"
       }
    }
}

可能的原因

导致 502 Bad Gateway Error 的一个常见原因是Unexpected EOF 错误,这可能是由以下原因导致的:

原因 详细信息 指定步骤
目标服务器配置不正确 目标服务器未正确配置,无法支持 TLS/SSL 连接。 Edge 公有云和私有云用户
后端服务器抛出 EOFException 后端服务器可能会突然发送 EOF。 仅面向 Edge Private Cloud 用户
保持活动超时配置不正确 使 Apigee 和后端服务器上的活动超时配置不正确。 Edge 公有云和私有云用户

常见诊断步骤

您可以使用以下任一方法诊断错误:

API 监控

<ph type="x-smartling-placeholder">

如需使用 API Monitoring 诊断错误,请执行以下操作:

借助 API Monitoring,您可以 502 错误,按照 调查问题。即:

  1. 前往调查信息中心。
  2. 从下拉菜单中选择 Status Code (状态代码),并确保正确的时间 在发生 502 个错误时选择了时间段。
  3. 如果您看到大量 502 错误,请点击矩阵中的复选框。
  4. 点击右侧的查看日志,查看 502 错误, 如下所示:
  5. 在这里,我们可以看到以下信息:

    • Fault Sourcetarget
    • 错误代码messaging.adaptors.http.UnexpectedEOFAtTarget

这表示 502 错误是由目标因意外的 EOF 引起的。

此外,请记下 502 错误的 Request Message ID,以便后续 调查。

跟踪工具

如需使用跟踪工具诊断错误,请执行以下操作:

<ph type="x-smartling-placeholder">
  1. 启用 跟踪会话,并执行 API 调用以重现问题 502 Bad Gateway
  2. 选择其中一个失败请求并检查跟踪记录。
  3. 浏览跟踪记录的各个阶段,并找到失败的位置。
  4. 请求发送到目标服务器后,您应该会看到失败错误,如下所示:

    alt_text

    alt_text

  5. 确定 X-Apigee.fault-sourceX-Apigee.fault-codeAX(记录的 Google Analytics 数据)跟踪记录中的阶段

    如果 X-Apigee.fault-sourceX-Apigee.fault-code 的值与 值,您可以确认 502 错误是 来自目标服务器的链接:

    响应标头
    X-Apigee.fault-source target
    X-Apigee.fault-code messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    此外,请记下 502 错误的 X-Apigee.Message-ID 以进行进一步调查。

NGINX 访问日志

<ph type="x-smartling-placeholder">

如需使用 NGINX 诊断错误,请执行以下操作:

您还可以参考 NGINX 访问日志来确定导致 502 状态的原因 代码。如果相应问题在过去发生过或 并且无法在界面中捕获跟踪记录。使用以下步骤 从 NGINX 访问日志中确定此信息:

  1. 查看 NGINX 访问日志。
    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
  2. 搜索特定 API 代理在特定时间段内发生的任何 502 错误 (如果问题在过去发生过)或针对 502 仍失败的任何请求。
  3. 如果存在任何 502 错误,则检查错误是否由目标所致 发送 Unexpected EOF。如果 X-Apigee.fault-sourceX- Apigee.fault-code 与下表中显示的值相匹配,但 502 错误为 由目标意外关闭连接导致:
    响应标头
    X-Apigee.fault-source target
    X-Apigee.fault-code messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    以下条目示例显示了由目标服务器导致的 502 错误:

此外,请记下 502 错误的消息 ID,以便展开进一步调查。

原因:目标服务器配置不正确

目标服务器未正确配置,无法支持 TLS/SSL 连接。

诊断

  1. 使用 API 监控跟踪工具NGINX 访问日志,用于确定消息 ID。 故障代码和 502 错误的故障来源。
  2. 在界面中为受影响的 API 启用跟踪记录。
  3. 如果失败 API 请求的跟踪记录显示以下内容: <ph type="x-smartling-placeholder">
      </ph>
    1. 目标流请求开始后,会立即出现 502 Bad Gateway 错误。
    2. error.class 会显示 messaging.adaptors.http.UnexpectedEOF.

      那么,此问题很可能是由目标服务器不正确导致的 配置。

  4. 使用 Edge Management API 调用获取目标服务器定义: <ph type="x-smartling-placeholder">
      </ph>
    1. 如果您是公有云用户,请使用以下 API:
      curl -v https://api.enterprise.apigee.com/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
      
    2. 如果您是 Private Cloud 用户,请使用以下 API:
      curl -v http://<management-server-host>:<port #>/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
      

      错误的 TargetServer 定义示例:

      <TargetServer  name="target1">
        <Host>mocktarget.apigee.net</Host>
        <Port>443</Port>
        <IsEnabled>true</IsEnabled>
      </TargetServer >
      
  5. 图例中的 TargetServer 定义是一个典型的 错误配置,具体说明如下:

    假设已配置目标服务器 mocktarget.apigee.net 以通过端口 443 接受安全 (HTTPS) 连接。但是,如果您观察 目标服务器定义,没有任何其他属性/标志可表明 旨在确保安全连接这会使 Edge 将发往 特定目标服务器作为 HTTP(非安全)请求发送。因此 Edge 不会 与此目标服务器启动 SSL 握手过程。

    由于目标服务器配置为在 443 上仅接受 HTTPS (SSL) 请求,因此它将 拒绝来自 Edge 的请求或关闭连接。因此,您获得了 消息处理器出现 UnexpectedEOFAtTarget 错误。消息处理器将发送 502 Bad Gateway 作为对客户端的响应。

分辨率

始终确保根据您的要求正确配置目标服务器。

对于上面说明的示例,如果您想要向安全 (HTTPS/SSL) 目标发送请求, 您需要添加 SSLInfo 属性并设置 enabled 标志 发送至 true。虽然可以在目标环境中为目标服务器添加 SSLInfo 属性, 端点定义本身,建议将 SSLInfo 属性添加为目标的一部分, 服务器定义以避免混淆。

  1. 如果后端服务需要单向 SSL 通信,则: <ph type="x-smartling-placeholder">
      </ph>
    1. 您需要通过添加 SSLInfoTargetServer 定义中启用 TLS/SSL 属性,其中 enabled 标志设置为 true,如下所示:
      <TargetServer name="mocktarget">
        <Host>mocktarget.apigee.net</Host>
        <Port>443</Port>
        <IsEnabled>true</IsEnabled>
        <SSLInfo>
            <Enabled>true</Enabled>
        </SSLInfo>
      </TargetServer>
      
    2. 如果您想在 Edge 中验证目标服务器的证书,则还需要 添加信任库(包含目标服务器的证书),如下所示:
      <TargetServer  name="mocktarget">
          <Host>mocktarget.apigee.net</Host>
          <Port>443</Port>
          <IsEnabled>true</IsEnabled>
          <SSLInfo>
              <Ciphers/>
              <ClientAuthEnabled>false</ClientAuthEnabled>
              <Enabled>true</Enabled>
              <IgnoreValidationErrors>false</IgnoreValidationErrors>
              <Protocols/>
              <TrustStore>mocktarget-truststore</TrustStore>
          </SSLInfo>
      </TargetServer>
      
  2. 如果后端服务需要双向 SSL 通信,则: <ph type="x-smartling-placeholder">
      </ph>
    1. 您需要具有 ClientAuthEnabledSSLInfo 属性, KeystoreKeyAliasTruststore 标志设置正确,如下所示:
      <TargetServer  name="mocktarget">
           <IsEnabled>true</IsEnabled>
           <Host>www.example.com</Host>
           <Port>443</Port>
           <SSLInfo>
               <Ciphers/>
               <ClientAuthEnabled>true</ClientAuthEnabled>
               <Enabled>true</Enabled>
               <IgnoreValidationErrors>false</IgnoreValidationErrors>
               <KeyAlias>keystore-alias</KeyAlias>
               <KeyStore>keystore-name</KeyStore>
               <Protocols/>
               <TrustStore>truststore-name</TrustStore>
           </SSLInfo>
        </TargetServer >
      

参考

负载均衡 可跨后端服务器

原因:后端服务器出现 EOFException

后端服务器可能会突然发送 EOF(文件结束)。

诊断

  1. 使用 API 监控跟踪工具NGINX 访问日志,用于确定消息 ID。 故障代码和 502 错误的故障来源。
  2. 检查消息处理器日志 (/opt/apigee/var/log/edge-message-processor/logs/system.log) 并搜索,看看您是否 具有特定 API 的 eof unexpected,或者该 API 具有唯一的 messageid 请求,那么您可以进行搜索。

    消息处理器日志中的异常堆栈轨迹示例

    "message": "org:myorg env:test api:api-v1 rev:10 messageid:rrt-1-14707-63403485-19 NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context$3.onException() : SSLClientChannel[C:193.35.250.192:8443 Remote host:0.0.0.0:50100]@459069 useCount=6 bytesRead=0 bytesWritten=755 age=40107ms lastIO=12832ms .onExceptionRead exception: {}
    java.io.EOFException: eof unexpected
    at com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:45) ~[nio-1.0.0.jar:na]
    at com.apigee.nio.channels.InputChannel.read(InputChannel.java:103) ~[nio-1.0.0.jar:na]
    at com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:79) ~[http-1.0.0.jar:na]
    at com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(NIOSupport.java:51) [nio-1.0.0.jar:na]
    at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:123) [nio-1.0.0.jar:na]"
    

    在上例中,您可以看到消息处理器尝试从 中读取响应时发生 java.io.EOFException: eof unexpected 错误。 后端服务器此异常表示文件结束 (EOF) 或直播结束时存在 意外到达。

    也就是说,消息处理器将 API 请求发送到后端服务器,并正在等待 或读取响应内容。但是,后端服务器突然终止了连接 或者可以读取完整的响应。

  3. 检查后端服务器日志,看看是否存在 导致后端服务器突然终止连接。如果您发现 错误/信息,然后转到解决方法 并在后端服务器中适当修正问题。
  4. 如果您在后端服务器中未发现任何错误或信息,请收集消息处理器上的 tcpdump 输出:
    1. 如果您的后端服务器主机只有一个 IP 地址,请使用以下命令:
      tcpdump -i any -s 0 host IP_ADDRESS -w FILE_NAME
      
    2. 如果您的后端服务器主机有多个 IP 地址,请使用以下命令:
      tcpdump -i any -s 0 host HOSTNAME -w FILE_NAME
      

      通常,由于后端服务器在响应中返回了 [FIN,ACK]

  5. 请参考以下 tcpdump 示例。

    502 Bad Gateway Error 时截取的 tcpdump 示例 (UnexpectedEOFAtTarget) 发生

  6. TCPDump 输出中,您会注意到以下事件序列: <ph type="x-smartling-placeholder">
      </ph>
    1. 在数据包 985 中,消息处理器将 API 请求发送到后端服务器。
    2. 在数据包 986 中,后端服务器立即返回 [FIN,ACK]
    3. 在数据包 987 中,消息处理器向后端返回 [FIN,ACK] 服务器。
    4. 最终,连接会关闭,两端的 [ACK][RST]
    5. 由于后端服务器会发送 [FIN,ACK],因此您会遇到异常 Message 的 java.io.EOFException: eof unexpected 异常 处理器。
  7. 如果后端服务器发生网络问题,就可能会发生这种情况。与人脉网络互动 以便进一步调查此问题。

分辨率

适当修正后端服务器上的问题。

如果问题仍然存在,并且您需要有关排查 502 Bad Gateway Error 或您 怀疑这是 Edge 中的问题,请与 Apigee Edge 支持联系。

原因:保持连接超时配置不正确

在诊断这是否是导致 502 错误的原因之前,请仔细阅读 以下概念。

Apigee 中的永久性连接

默认情况下,Apigee(在下文中采用 HTTP/1.1 标准)使用永久性连接 在与目标后端服务器通信时发出通知。持久连接可以提高性能 方法是允许重复使用已建立的 TCP 和(如适用)TLS/SSL 连接 降低延迟开销连接需要保持的时长由系统控制 保持活动超时 (keepalive.timeout.millis)。

后端服务器和 Apigee 消息处理器都使用保持活跃超时来 相互打开的连接。一旦在保持连接超时内未收到任何数据 则后端服务器或消息处理器可以关闭彼此之间的连接。

默认情况下,将 API 代理部署到 Apigee 中的消息处理器时,将保持活跃超时设置为 60s,除非被替换。如果未收到 60s 的数据,Apigee 将 断开与后端服务器的连接。后端服务器还会保持保持活动超时 到期后,后端服务器将关闭与消息处理器的连接。

不正确的保持活动超时配置的影响

如果 Apigee 或后端服务器配置了错误的保持连接超时,则 会引发竞态条件,这会导致后端服务器在响应资源请求时发送意外的 End Of File (FIN)

例如,如果在 API 代理或 处理器值大于或等于上游后端服务器的超时时间,则 可能会出现以下竞态条件。也就是说,如果消息处理器未收到任何 直到非常接近后端服务器保持活跃超时状态的阈值, 并使用现有连接发送到后端服务器。这可能会导致 由于发生意外 EOF 错误而导致的 502 Bad Gateway,如下所述:

  1. 假设消息处理器和后端服务器都设置了保持活跃状态超时 是 60 秒,并且没有新的 直到前一个请求发出后 59 秒, 消息处理器。
  2. 消息处理器继续处理在第 59 秒收到的请求 使用现有连接(因为 keepalive 超时尚未过),并将 发送到后端服务器。
  3. 但是,在请求到达后端服务器之前,保持活动超时 已超出后端服务器上的阈值。
  4. 消息处理器对资源的请求正在进行中,但后端服务器 尝试通过向 Message 发送 FIN 数据包来关闭连接 处理器。
  5. 当消息处理器等待接收数据时,它会改为接收 意外的 FIN,并且连接被终止。
  6. 这将生成 Unexpected EOF,随后 502 由消息处理器返回给客户端

在本例中,我们发现 502 错误之所以发生,是因为相同的保持活动超时 消息处理器和后端服务器都配置了 60 秒的值。同样, 如果为邮件/消息/帖子或消息 与后端服务器上相比

诊断

  1. 如果您是公有云用户: <ph type="x-smartling-placeholder">
      </ph>
    1. 使用 API Monitoring 或 Trace 工具(如 常见诊断步骤),并验证您是否满足以下两个条件: 设置: <ph type="x-smartling-placeholder">
        </ph>
      • 错误代码messaging.adaptors.http.flow.UnexpectedEOFAtTarget
      • 故障来源target
    2. 请参阅使用 tcpdump 以展开进一步调查。
  2. 如果您是 Private Cloud 用户: <ph type="x-smartling-placeholder">
      </ph>
    1. 使用 Trace 工具NGINX 访问日志来确定消息 ID。 错误代码和 502 错误的故障来源。
    2. 在消息处理器日志中搜索消息 ID
      /opt/apigee/var/log/edge-message-processor/logs/system.log)。
    3. 您将看到如下所示的 java.io.EOFEXception: eof unexpected
      2020-11-22 14:42:39,917 org:myorg env:prod api:myproxy rev:1 messageid:myorg-opdk-dc1-node2-17812-56001-1  NIOThread@1 ERROR HTTP.CLIENT - HTTPClient$Context$3.onException() :  ClientChannel[Connected: Remote:51.254.225.9:80 Local:10.154.0.61:35326]@12972 useCount=7 bytesRead=0 bytesWritten=159 age=7872ms  lastIO=479ms  isOpen=true.onExceptionRead exception: {}
              java.io.EOFException: eof unexpected
              at com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:45)
              at com.apigee.nio.channels.InputChannel.read(InputChannel.java:103)
              at com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:80)
              at com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(NIOSupport.java:51)
              at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:220)
      
    4. 错误 java.io.EOFException: eof unexpected 表示 消息处理器收到 EOF,而它仍在等待读取 发送响应。
    5. 上述错误消息中的属性 useCount=7 表示 消息处理器已重复使用此连接约七次,且属性 bytesWritten=159 表示消息处理器已发送 向后端服务器发送 159 个字节的有效负载。但是它收到了零字节 在发生意外 EOF 时返回。
    6. 这表明消息处理器已多次重复使用同一连接, 这次,它发送了数据,但不久后就收到了 EOF 才会出现这种错误。也就是说,后端很可能 服务器的 keep-alive 超时时间短于或等于 API 代理中设置的时长。

      如下所述,您可以在 tcpdump 的帮助下进一步调查。

使用 tcpdump

  1. 使用以下命令在后端服务器上捕获 tcpdump
    tcpdump -i any -s 0 host MP_IP_Address -w File_Name
    
  2. 分析捕获的 tcpdump

    以下是 tcpdump 输出的示例

    在上面的 tcpdump 示例中,您可以看到以下内容:

    1. 在数据包 5992, 中,后端服务器收到了 GET 请求。
    2. 在数据包 6064 中,它返回 200 OK.
    3. 在数据包 6084 中,后端服务器收到了另一个 GET 请求。
    4. 在数据包 6154 中,它使用 200 OK 进行响应。
    5. 在数据包 6228 中,后端服务器收到了第三个 GET 请求。
    6. 这一次,后端服务器向消息处理器返回 FIN, ACK (数据包 6285)开始关闭连接。

    此示例中成功地重复使用了同一连接两次,但在第三个请求中, 后端服务器发起连接关闭的发起,而消息处理器 等待来自后端服务器的数据这表明后端服务器的 实时超时很有可能短于或等于 API 代理中设置的值。进行验证 请参阅比较 Apigee 和后端服务器上的持久连接超时

比较 Apigee 和后端服务器上的 keepalive 超时

  1. 默认情况下,Apigee 将保持活跃状态超时属性的值设为 60 秒。
  2. 不过,您可能覆盖了 API 代理中的默认值。 您可以通过查看TargetEndpoint 失败的 API 代理,产生 502 个错误。

    TargetEndpoint 配置示例

    <TargetEndpoint name="default">
      <HTTPTargetConnection>
        <URL>https://mocktarget.apigee.net/json</URL>
        <Properties>
          <Property name="keepalive.timeout.millis">30000</Property>
        </Properties>
      </HTTPTargetConnection>
    </TargetEndpoint>
    

    在上面的示例中,将保持活动超时属性替换为 30 秒(30000 毫秒)。

  3. 接下来,请检查后端服务器上配置的保持活动超时属性。假设 您的后端服务器配置的值为 25 seconds
  4. 如果您确定 Apigee 上的保持活动超时属性值较高 高于后端服务器上的 keepalive 超时属性值(如上所示) 那么这就是导致 502 错误的原因。

分辨率

确保 Apigee 上的保持活动超时属性始终较低(在 API 代理和 消息处理器组件)与后端服务器上的组件进行对比。

  1. 确定为后端服务器上的 keepalive 超时设置的值。
  2. 在 API 代理中为“保持活动状态超时”属性配置适当的值,或者 消息处理器,以使保持活动超时属性小于 设置后端服务器 <ph type="x-smartling-placeholder"></ph> 为消息处理器配置 keepalive 超时

如果问题仍然存在,请转到必须收集诊断信息

最佳做法

强烈建议下游组件始终具有较低的保持活跃超时时间 高于上游服务器上配置的阈值,以避免这些类型的竞态条件和 502 个错误。每个下游跃点应低于每个上游跃点。在 Apigee 中 Edge,最好遵循以下准则:

  1. 客户端保持活动超时时间应小于边缘路由器保持活动超时时间。
  2. 边缘路由器保持连接超时的时限应短于消息处理器保持连接超时的时间。
  3. 消息处理器的持久连接超时应小于目标服务器保持连接超时。
  4. 如果 Apigee 前面或后面有任何其他跃点,则也应该应用相同的规则。 您应始终让下游客户端关闭 与上游连接。

必须收集诊断信息

按照上述说明操作后,如果问题依然存在,请收集以下内容 然后联系 Apigee Edge 支持团队

如果您是公有云用户,请提供以下信息:

  • 组织名称
  • 环境名称
  • API 代理名称
  • 完成 curl 命令以重现 502 错误
  • 包含具有 502 Bad Gateway - Unexpected EOF 错误的请求的跟踪文件
  • 如果 502 错误目前未发生,请提供包含 过去发生 502 个错误时的时区信息。

如果您是 Private Cloud 用户,请提供以下信息:

  • 观察到失败请求的完整错误消息
  • 您要观察的组织、环境名称和 API 代理名称 502 个错误
  • API 代理软件包
  • 包含具有 502 Bad Gateway - Unexpected EOF 错误的请求的跟踪文件
  • NGINX 访问日志
    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
  • 消息处理器日志
    /opt/apigee/var/log/edge-message-processor/logs/system.log
  • 发生 502 错误时包含时区信息的时间段
  • Tcpdumps 在出错时收集在消息处理器和/或后端服务器上 发生了