502 网关无效 - DuplicateHeader

您正在查看 Apigee Edge 文档。
转到 Apigee X 文档
info

问题

客户端应用收到 HTTP 状态代码 502 Bad Gateway,错误代码为 protocol.http.DuplicateHeader ,以此响应 API 调用。

出错提示

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

HTTP/1.1 502 Bad Gateway

此外,您可能会看到类似于以下内容的错误消息:

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

可能的原因

如果特定 HTTP 标头不允许在 Apigee Edge 中包含重复项,并且它作为后端服务器发送到 Apigee Edge 的 HTTP 响应的一部分出现相同或不同的值,则会出现此错误。

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

造成此错误的可能原因包括:

原因 说明 适用的问题排查说明
响应中的重复标头 后端服务器返回的响应包含重复标头。 Edge Public 和 Private Cloud 用户

常见诊断步骤

请使用以下工具/方法之一来诊断此错误:

API 监控

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

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

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

    查看放大图片

  8. 系统会显示有关故障代码 protocol.http.DuplicateHeader 的信息,如下所示:

    查看放大图片

  9. 确保 Status Code502,如上例所示。
  10. 点击 View logs ,然后展开失败请求对应的行。
  11. 在“Logs”窗口中,记下以下详细信息:

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

Trace 工具

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

  1. 启用 跟踪会话,然后执行以下任一操作:
    1. 等待 502 Bad Gateway 错误发生,或者
    2. 如果您可以重现此问题,请进行 API 调用并重现 502 Bad Gateway 错误
  2. 确保已启用显示所有 FlowInfo

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

    查看放大图片

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

    上面的示例跟踪记录显示错误为 Duplicate Header "Expires"。由于此错误是在请求发送到后端服务器后由 Apigee 引发的,因此表示后端服务器多次发送了标头 Expires

  7. 前往跟踪记录中的 AX (已记录分析数据)阶段,然后点击该阶段。
  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. 如果您确实发现任何 502 错误,并且 X-Apigee-fault-code protocol.http.DuplicateHeader的值匹配,请 确定 X-Apigee-fault-source 的值。

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

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

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

原因:响应中的重复标头

诊断

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

    出错提示

    使用错误消息

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

      示例错误消息

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

    实际请求

    使用实际请求

    1. 如果您无法访问向目标服务器发出的实际请求,请从 使用 Trace 工具的第 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 provides a CwC property HTTPHeader.<HeaderName>,该属性允许客户端应用和目标 服务器向 Apigee Edge 中的 API 代理发送重复标头。

CwC 属性
HTTPHeader.<HeaderName> allowDuplicates,multivalued

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

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

规范

Apigee 会返回 502 Bad Gateway 错误响应,因为它预计 后端服务器会按照以下 RFC 规范运行:

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

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

必须收集的诊断信息

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

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

  • 组织名称
  • 环境名称
  • 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