502 网关无效 - DuplicateHeader

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

问题

客户端应用收到 HTTP 状态代码 502 Bad Gateway(错误代码为 protocol.http.DuplicateHeader )作为 API 调用的响应。

错误消息

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

HTTP/1.1 502 Bad Gateway

此外,您可能还会看到类似于如下所示的错误消息:

{
   "fault":{
      "faultstring":"Duplicate Header \"Expires\"",
      "detail":{
         "errorcode":"protocol.http.DuplicateHeader"
      }
   }
}

可能的原因

如果在后端服务器向 Apigee Edge 发送的 HTTP 响应中多次出现同一 HTTP 标头,但 Apigee Edge 中不允许有相同或不同的值,则会出现此错误。

根据 RFC 7230 第 3.2.2 节:字段顺序发件人不得在消息中生成多个具有相同字段名称的标头字段,除非相应标头字段的整个字段值被定义为以英文逗号分隔的列表 [即#(values)] 或标头字段是一个众所周知的例外情况。如果 Apigee Edge 发现,在目标/后端服务器发送的 HTTP 响应 中多次发送了一个不允许存在重复项的特定相同标头,则会返回 502 Bad Gateway 和错误代码 protocol.http.DuplicateHeader

以下是导致此错误的可能原因:

原因 说明 适用的问题排查说明
响应中的标头重复 来自后端服务器的响应包含重复标头。 Edge 公有云和私有云用户

常见诊断步骤

使用以下工具/技巧之一来诊断此错误:

API 监控

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

  1. 以拥有 适当角色的用户身份 登录 Apigee Edge 界面
  2. 切换到您要调查问题的组织。

  3. 前往 Analyze > API Monitoring > Investigate 页面。
  4. 选择您观察到错误的具体时间范围。
  5. 确保将代理过滤器设置为全部
  6. 根据时间绘制故障代码
  7. 选择包含错误代码 protocol.http.DuplicateHeader 的单元格,如下所示:

    查看放大图片

  8. 错误代码 protocol.http.DuplicateHeader 的相关信息如下所示:

    查看放大图片

  9. 确保状态代码502,如上例所示。
  10. 点击查看日志,然后展开失败请求所在的行。
  11. 在“日志”窗口中,请注意以下详细信息:

    • 状态代码502
    • 错误来源target
    • 错误代码protocol.http.DuplicateHeader
  12. 故障来源target,表示来自后端服务器的响应包含重复的标头。

跟踪工具

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

  1. 启用跟踪会话,然后:
    1. 等待 502 Bad Gateway 错误发生,或者
    2. 如果您可以重现问题,请进行 API 调用并重现 502 Bad Gateway 错误
  2. 确保已启用 Show all Flow Infos(显示所有流信息):

  3. 选择其中一个失败的请求并检查跟踪记录。
  4. 浏览跟踪记录的不同阶段,并找到失败的位置。
  5. 通常情况下,您会在请求发送到目标服务器阶段之后的流程中发现此错误,如下所示:

    查看放大图片

  6. 记下跟踪记录中的错误值。

    上面的示例轨迹将错误显示为 Duplicate Header "Expires"。由于该错误在请求发送到后端服务器后由 Apigee 引发,因此表示后端服务器多次发送标头 Expires

  7. 进入跟踪记录中的 AX(已记录 Google Analytics(分析)数据)阶段,然后点击该阶段。
  8. 向下滚动到 Phase Details - Response Headers(阶段详细信息 - 响应标头)部分,并确定 X-Apigee-fault-codeX-Apigee-fault-source 的值,如下所示:

    查看放大图片

  9. 您将看到 X-Apigee-fault-codeX-Apigee-fault-source 的值为 protocol.http.DuplicateHeadertarget,这表示此错误是因为后端服务器为响应标头 Expires 传递了重复标头。
    响应标头
    X-Apigee-fault-code protocol.http.DuplicateHeader
    X-Apigee-fault-source target
  10. 检查您是否在使用代理链;也就是说,目标服务器或目标端点是否正在调用 Apigee 中的另一个代理。

    1. 如需确定这一点,请导航回发送到目标的请求服务器阶段。点击 Show Curl

    2. 此时将打开 Curl for Request Sent to Target Server 窗口,您可以从中确定目标服务器主机别名。

    3. 如果目标服务器主机别名指向虚拟主机别名,则它是代理链。在这种情况下,您需要对链式代理重复上述所有步骤,直到确定导致 502 Bad Gateway 错误的实际原因。
    4. 如果目标服务器主机别名指向后端服务器,则表示您的后端服务器在向 Apigee 的响应中发送重复的标头。

NGINX

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

  1. 如果您是 Private Cloud 用户,则可以使用 NGINX 访问日志来确定有关 HTTP 502 错误的关键信息。
  2. 检查 NGINX 访问日志:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    其中:将 ORGENVPORT# 替换为实际值。

  3. 搜索以查看在特定持续时间内是否存在任何 502 错误(如果问题是在过去发生的),或者是否有任何请求仍然失败并显示 502
  4. 如果您确实发现 X-Apigee-fault-code X-Apigee-fault-code 的值匹配的任何 502 错误,则确定 X-Apigee-fault-code 的值。

    NGINX 访问日志中的 502 错误示例

    NGINX Access 日志中的上述示例条目具有 X- Apigee-fault-codeX-Apigee-fault-source 的以下值:

    响应标头
    X-Apigee-fault-code protocol.http.DuplicateHeader
    X-Apigee-fault-source target

原因:响应中包含重复的标头

诊断

  1. 按照常见诊断步骤中所述,使用 API Monitoring 或 NGINX 访问日志确定观察到的错误的故障代码故障来源
  2. 如果故障来源的值为 target,则表示目标服务器发送的响应包含重复标头。
  3. 您可以使用以下方法之一确定在响应中作为响应的一部分发送多次的实际标头:

    错误消息

    使用错误消息

    1. 如果您有权访问从 Apigee Edge 收到的完整错误消息,请参阅faultstringfaultstring 包含已发送多次的标头名称。

      示例错误消息:

      "faultstring":"Duplicate Header \"Expires\""
      
    2. 在上述错误消息中,您可以看到标头 Expires 被发送多次,如 faultstring 中所示。

    实际请求

    使用实际请求

    1. 如果您无法访问向目标服务器发出的实际请求,请从使用跟踪工具第 10.a 步和第 10.b 步获取相应的 curl 命令。
    2. 如果您有权访问向目标服务器应用发出的实际请求,请执行以下步骤:

      1. 调用目标服务器。

        针对此示例中使用的目标服务器的示例请求

        curl -X GET "https://BACKEND_SERVER_HOST/response-headers?Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT&Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT" -v
        
      2. 验证响应中显示的标头列表。

        此示例中使用的来自目标服务器的响应示例

        * ...Trimmed...
        > GET /response-headers?Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT&Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT HTTP/2
        > Host: BACKEND_SERVER_HOST
        > User-Agent: curl/7.64.1
        > Accept: */*
        >
        * Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
        < HTTP/2 200
        < date: Fri, 02 Jul 2021 05:29:07 GMT
        < content-type: application/json
        < content-length: 166
        < server: gunicorn/19.9.0
        < Expires: Mon, 21 June 2021 07:28:00 GMT
        < Expires: Mon, 21 June 2021 07:28:00 GMT
        < access-control-allow-origin: *
        < access-control-allow-credentials: true
        <
        ----<Response BODY>------
        * Connection #0 to host httpbin.org left intact
        * Closing connection 0
        

        在上面的示例中,标头 Expires 会发送多次。因此,此请求会失败,并显示 502 Bad Gateway 错误和错误代码:protocol.http.DuplicateHeader

      3. 如果名称出现在 faultstring 中的标头在后端服务器的响应中出现多次,则这就是导致此错误的原因。在上述情况下,系统会多次发送标头 Expires

分辨率

解决重复问题

方法 1 [推荐做法] 修复后端服务器,以免包含重复的标头

  1. 分析特定后端服务器发送重复标头 Expires 的原因,并验证 API 代理是否可以接受该标头。在大多数情况下,根据 HTTP 规范 RFC7230 的规定是不可取的。
  2. 如果您不希望发送重复的标头,请修改目标服务器应用。 在上面讨论的示例中,请注意,标头 Expires 会以相同的值发送两次,这种情况是不可取的。要解决此问题,请确保目标服务器仅传递 Expires 标头一次。
  3. 如果可取且您希望允许使用重复的标头,请转到选项 2 使用 CwC 属性

CwC

选项 2 使用 CwC 属性

Apigee 提供 CwC 属性 HTTPHeader.<HeaderName>,可让客户端应用和目标服务器向 Apigee Edge 中的 API 代理发送重复标头。

CwC 媒体资源
HTTPHeader.<HeaderName> allowDuplicates,multivalued

例如,可以在消息处理器上设置以下属性,以允许标头 Expires 使用重复和多个值。

HTTPHeader.Expires=allowDuplicates, multiValued
  1. 如果您是私有云用户,则可以按照 配置消息处理器以使用重复标头方法指南,配置该属性以防止 Apigee Edge 引发 502 Bad Gateway 错误,即使请求包含重复的标头也是如此。
  2. 如果您是公有云用户,请联系 Apigee Edge 支持团队,为您的组织配置此属性。

规范

Apigee 会返回 502 Bad Gateway 错误响应,因为它预期后端服务器的行为符合以下 RFC 规范:

规范
RFC 7230,第 3.2.2 节:字段顺序
RFC 7230,第 3.2 节:标头字段

如果您仍然需要 Apigee 支持部门的任何帮助,请参阅 必须收集诊断信息

必须收集的诊断信息

收集以下诊断信息,然后联系 Apigee Edge 支持团队

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

  • 组织名称
  • 环境名称
  • API 代理名称
  • 完成用于重现 502 错误的 curl 命令
  • API 请求的跟踪文件

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

  • 观察到失败请求的完整错误消息
  • 环境名称
  • API 代理软件包
  • API 请求的跟踪文件
  • NGINX 访问日志:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    其中:将 ORGENVPORT# 替换为实际值。

  • 消息处理器系统日志 /opt/apigee/var/log/edge-message-processor/logs/system.log