HTTP(S) 负载平衡问题排查

本指南介绍如何排查 Google Cloud 外部 HTTP(S) 负载平衡器的配置问题。

概览

本指南中讨论的问题类型包括:

  • 后端具有不兼容的平衡模式时的设置问题
  • 常规连接问题
  • 目标为后端的 HTTP/2 连接的问题
  • 外部后端和互联网 NEG 问题
  • 无服务器 NEG 问题

准备工作

在调查问题之前,请先熟悉以下页面。

关于常规连接:

对于日志记录和监控:

后端具有不兼容的平衡模式

创建负载均衡器时,您可能会看到以下错误:

Validation failed for instance group INSTANCE_GROUP:

backend services 1 and 2 point to the same instance group
but the backends have incompatible balancing_mode. Values should be the same.

如果您尝试在两个不同的负载均衡器中使用同一后端,并且该后端没有兼容的平衡模式,则会发生此错误。

详情请参阅以下内容:

排查常规连接问题

原因不明的 502 错误

在完成负载平衡器配置后,如果 502 错误的持续时间超过几分钟,则可能是因为以下原因之一:

请按照以下步骤排查 502 响应的问题:

  1. 验证运行状况检查流量是否到达后端虚拟机。为此,请启用运行状况检查日志记录并搜索成功的日志条目。
  2. 检查 502 响应是由负载平衡器处理还是来自后端。执行以下步骤:

    1. 使用 Cloud Logging 查看负载平衡器的日志。您可创建查询,以便仅查找 502 响应代码
    2. 查看 statusDetails 字段的值。

      • 如果 statusDetails 返回成功消息(例如 response_sent_by_backend),则表示是正在处理 HTTP 502 响应的后端。 检查后端的日志并进一步排查问题,具体取决于后端上运行的服务。
      • 如果 statusDetails 返回失败消息,请参阅以下解决方案列表,了解与 502 响应相关的一些常见故障:
      statusDetail 失败消息 潜在原因和解决方案
      failed_to_connect_to_backend

      负载平衡器无法与后端建立连接。这可能意味着在后端上运行的服务不侦听后端服务中定义的端口。

      建议:

      • 将运行状况检查的端口设置为使用服务端口。这意味着,后端在能够处理实际流量之前会被判定为运行状况不佳。
      • 使用以下命令确保后端服务的已命名端口上运行了一项服务。
        
        $ netstat -tnl | grep PORT
      failed_to_pick_backend

      负载平衡器无法选择后端。这可能意味着所有后端运行状况都不佳。确保您已配置正确的运行状况检查防火墙规则

      backend_connection_closed_before_data_sent_to_client 响应代理至客户端之前,后端与负载平衡器的连接意外关闭。如果负载平衡器正在向另一个实体发送流量,就会发生这种情况。另一个实体可能是 TCP 超时时间短于负载平衡器的超时的第三方负载平衡器。如需了解详情,请参阅超时和重试
      backend_timeout 后端响应时间太长。后端服务超时可能设置得太短,导致给定服务无法响应。请考虑增加后端服务超时值,或查看服务响应时间较长的原因。

经过负载平衡处理的流量不含原始客户端的源地址

对于从负载平衡器到您实例的流量,其 IP 地址范围为 130.211.0.0/2235.191.0.0/16。查看负载平衡实例上的日志时,您无法看到原始客户端的源地址。相反,您会看到此范围的源地址。

在 Cloud Storage 存储分区上尝试查看对象时获取权限错误

为了通过负载平衡来传送对象,Cloud Storage 对象必须可公共访问。确保更新正在传送的对象的权限,使其公开可读

网址无法传送预期的 Cloud Storage 对象

需要传送的 Cloud Storage 对象基于您的网址映射和您请求的网址来确定。若请求路径映射到您网址映射中的后端存储分区,Cloud Storage 对象通过将完整请求路径附加到网址映射指定的 Cloud Storage 存储分区上来确定。

例如,如果您将 /static/* 映射到 gs://[EXAMPLE_BUCKET],则向 https://<GCLB IP or Host>/static/path/to/content.jpg 发出的请求将尝试传送 gs://[EXAMPLE_BUCKET]/static/path/to/content.jpg。如果该对象不存在,您将获得以下错误消息而非该对象:


NoSuchKey
The specified key does not exist.

未执行压缩

HTTP(S) 负载平衡本身不会对响应进行压缩或解压缩,但它可以提供由后端服务生成的响应,这些响应会使用 gzipDEFLATE 等工具进行压缩。

如果由 HTTP(S) 负载平衡提供的响应未被压缩,但本应进行压缩,请仔细检查以确保您实例上运行的 Web 服务器软件已配置为压缩响应。默认情况下,某些 Web 服务器软件会对包含 Via 标头的请求自动停用压缩功能,该标头表示请求由代理转发。HTTP(S) 负载平衡代理会依据 HTTP 规范的要求为每个请求添加一个 Via 标头。如需启用压缩功能,您可能必须覆盖网络服务器的默认配置,以指示其对响应进行压缩(即便是请求中包含了 Via 标头)。

如需配置 nginx 后端以传送通过外部 HTTP(S) 负载平衡器代理的压缩响应,请执行以下操作:

如需配置 Apache 后端以传送通过外部 HTTP(S) 负载平衡器代理的压缩响应,请执行以下操作:

解决 HTTP 408 错误

借助 HTTP 流量,客户端完成发送其请求的最长时间等于后端服务超时值。如果看到带有 jsonPayload.statusDetail client_timed_out 的 HTTP 408 响应,则表示客户端的请求被代理或者后端的响应被代理时跟不上进度。如果问题是由于客户端遇到性能问题,您可以通过增加后端服务超时值来解决此问题。

排查后端 HTTP/2 问题

字段 resource.loadBalancingScheme 的下列值无效:'EXTERNAL'

如果您在创建后端服务时未选择“全球”选项,可能会发生这种情况。当您按如下方式发出 gcloud 命令时,系统会提示您指定地区或将负载平衡器指定为全球负载平衡器:

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test1 \
    --protocol=http2

对于以下后端服务,系统会显示以下提示:

- [service-test] choose a region or global:
[1] global
[2] region: [REGION_A_NAME]
[3] region: [REGION_B_NAME]
....
Please enter your numeric choice:

对于 HTTP(S) 负载平衡器,后端服务必须是全球的,因此您必须选择选项 1 或发出带有 --global 选项的 gcloud 命令:

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test \
    --protocol=http2 \
    --global

原因不明的 502 错误

请确保您的后端实例运行状况良好且支持 HTTP/2 协议。您可以通过使用 HTTP/2 测试与后端实例的连接来验证这一点。确保该虚拟机使用符合 HTTP/2 规范的加密套件。例如,某些 TLS 1.2 加密套件不受 HTTP/2 支持。请参阅 TLS 1.2 加密套件黑名单

验证该虚拟机使用 HTTP/2 协议后,请确保您的防火墙设置允许运行状况检查程序和负载平衡器进行直通访问。

如果防火墙设置没有问题,请确保负载平衡器已配置为与该虚拟机上的正确端口通信。

排查外部后端和互联网 NEG 问题

在调查问题之前,请先熟悉以下页面。

流量未到达端点

配置服务后,在以下情况下,可通过外部 HTTP(S) 负载平衡器访问新端点:

  • 端点已关联到互联网 NEG。
  • 相关联的 FQDN 可以得到成功 DNS 解析(如果您使用的是 FQDN 端点类型)。
  • 端点可通过互联网访问。

如果流量无法到达端点,从而导致出现 HTTP(s) 的 502 错误代码,请检查以下内容:

  • 使用 dig 或 nslookup 这类工具来查询 _cloud-eoips.googleusercontent.com DNS TXT 记录。请记下(ip4: 后面的)CIDR 并确保您的防火墙或云端访问控制列表 (ACL) 允许使用这些范围。

配置外部后端后,向外部后端发出的请求失败,并显示 5xx 错误

  • 检查日志记录
  • 验证网络端点组为外部后端配置了正确的 IP:Port 或 FQDN:Port。
  • 如果您使用的是 FQDN,请确保它可以通过 Google 公共 DNS 进行解析。您可以使用上述步骤直接使用网页界面验证 FQDN 是否可通过 Google 公共 DNS 进行解析。
  • 如果您目前仅通过外部 IP 地址访问 HTTP(S) 负载平衡器,且您的源 Web 服务器需要主机名,请确保您正在通过配置自定义请求标头向后端发送有效的 HTTP 主机标头。
  • 如果通过 HTTPS 或 HTTP2(在后端服务的 protocol 字段中设置)与后端进行的通信配置为 INTERNET_FQDN_PORT 外部后端端点,请确保您的源站展示有效的 TLS (SSL) 证书,同时配置的 FQDN 与证书的 SAN 列表中的 SAN(主题备用名称)匹配。有效证书指由公共证书授权机构签发且未过期的证书。
  • 使用 INTERNET_FQDN_PORT 外部后端端点时,HTTPS 负载平衡器不接受自签名证书,并且会拒绝此类证书。
  • 如果将 HTTPS 或 HTTP/2 与 INTERNET_IP_PORT 类型的端点结合使用,则系统不会执行 SSL 证书验证/SAN 检查。这意味着可以使用自签名证书。使用 SSL 时,我们建议使用 INTERNET_FQDN_PORT 端点来确保服务器证书和 SAN 得到验证。

来自我的外部后端的响应不被 Cloud CDN 缓存

确保:

  • 通过将 enableCDN 设为 true,您已在包含指向外部后端的 NEG 的后端服务上启用 Cloud CDN。
  • 您的外部后端提供的响应符合 Cloud CDN 缓存要求。例如,您从源站发送 Cache-Control: public, max-age=3600 响应标头。

排查无服务器 NEG 问题

在调查问题之前,请先熟悉以下页面。

请求失败并显示 404 错误

确保底层无服务器资源(例如 App Engine、Cloud Functions 或 Cloud Run 服务)仍在运行。如果无服务器资源已删除,但无服务器 NEG 仍然存在,则外部 HTTP(S) 负载平衡器会继续尝试将请求路由至不存在的服务。这会导致出现 404 响应。

通常,外部 HTTP(S) 负载平衡器无法检测底层无服务器资源是否按预期工作。这意味着如果一个地区中的服务返回错误,但该地区中的整体 Cloud Run、Cloud Functions 或 App Engine 基础架构正常运行,则外部 HTTP(S) 负载平衡器不会自动将流量定向到其他地区。将用户流量路由到服务的新版本之前,请务必对新版本进行全面测试。

处理网址掩码不匹配问题

如果将已配置的网址掩码应用于用户请求网址,但没有生成服务名称,或者导致生成不存在的服务名称,则负载平衡器可能会根据使用的无服务器计算平台,对这些不匹配问题进行不同的处理。

Cloud Run:如果网址掩码不匹配,则负载平衡器将返回 HTTP 错误 404(未找到)。

Cloud Functions:如果网址掩码不匹配,则负载平衡器将返回 HTTP 错误 404 (Not Found)。

App Engine:如果网址掩码不匹配,则 App Engine 会使用 dispatch.yaml 和 App Engine 的默认路由逻辑来确定将请求发送到哪个服务。